क्या कोई पायथन में __all__ समझा सकता है?


982

मैं अधिक से अधिक पायथन का उपयोग कर रहा हूं, और मैं __all__विभिन्न __init__.pyफाइलों में चर सेट को देखता रहता हूं । क्या कोई समझा सकता है कि यह क्या करता है?

जवाबों:


565

यह उस मॉड्यूल की सार्वजनिक वस्तुओं की सूची है, जिसकी व्याख्या की गई है import *। यह एक अंडरस्कोर से शुरू होने वाली हर चीज को छिपाने के डिफ़ॉल्ट को ओवरराइड करता है।


146
ऐसी वस्तुएं जो एक अंडरस्कोर के साथ शुरू होती हैं, या __all__यदि __all__मौजूद हैं, तो उनका उल्लेख नहीं किया जाता है, वे वास्तव में छिपी नहीं हैं; यदि आप उनके नाम जानते हैं तो उन्हें सामान्य रूप से पूरी तरह से देखा और एक्सेस किया जा सकता है। यह केवल एक "आयात *" के मामले में है, जिसे वैसे भी अनुशंसित नहीं किया जाता है, जो कि अंतर किसी भी भार को वहन करता है।
ब्रैंडन रोड्स

28
@BrandonRhodes: यह बिल्कुल सच नहीं है या तो: यह केवल आयात मॉड्यूल के लिए अनुशंसित है जिसे आप जानते हैं कि आपको इसके लिए डिज़ाइन किया गया है import *(जैसे कि उदाहरण के लिए tk)। एक अच्छा संकेत अगर यह मामला है __all__या मॉड्यूल के कोड में अंडरस्कोर के साथ शुरू होने वाले नामों की उपस्थिति है ।
उड़ती हुई भेड़

12
सार्वजनिक और आंतरिक इंटरफेस - python.org/dev/peps/pep-0008/#id50 , बेहतर आत्मनिरीक्षण का समर्थन करने के लिए, मॉड्यूल को __all__ विशेषता का उपयोग करके स्पष्ट रूप से अपने सार्वजनिक एपीआई में नामों की घोषणा करनी चाहिए। खाली सूची में __all__ सेट करना दर्शाता है कि मॉड्यूल में कोई सार्वजनिक एपीआई नहीं है।
डिबग

मुझे यकीन नहीं है कि अगर tkआज (या 2012 में, यहां तक ​​कि) जारी किए गए थे, तो अनुशंसित अभ्यास का उपयोग करना होगा from tk import *। मुझे लगता है कि अभ्यास को जड़ता के कारण स्वीकार किया जाता है, न कि जानबूझकर डिजाइन के कारण।
चेपनर

के रूप में BrandonRhodes बताते हैं कि यह वास्तव में सही नहीं है
duhaime

947

से जुड़ा हुआ है, लेकिन यहाँ स्पष्ट रूप से उल्लेख नहीं किया गया है, वास्तव में जब __all__उपयोग किया जाता है। यह इस बात की एक सूची है कि मॉड्यूल में किन प्रतीकों को परिभाषित किया गया है जब from <module> import *उन्हें मॉड्यूल पर उपयोग किया जाएगा।

उदाहरण के लिए, निम्नलिखित कोड foo.pyस्पष्ट रूप से प्रतीकों का निर्यात करता है barऔर baz:

__all__ = ['bar', 'baz']

waz = 5
bar = 10
def baz(): return 'baz'

इन प्रतीकों को तब आयात किया जा सकता है:

from foo import *

print(bar)
print(baz)

# The following will trigger an exception, as "waz" is not exported by the module
print(waz)

यदि __all__ऊपर टिप्पणी की गई है, तो यह कोड पूरा होने पर अमल करेगा, क्योंकि डिफ़ॉल्ट व्यवहार import *सभी प्रतीकों को आयात करने के लिए है जो दिए गए नाम स्थान से एक अंडरस्कोर से शुरू नहीं होता है।

संदर्भ: https://docs.python.org/tutorial/modules.html#importing-from-a-package

नोट: केवल व्यवहार को __all__प्रभावित करता है from <module> import *__all__जिन सदस्यों का उल्लेख नहीं किया गया है वे अभी भी मॉड्यूल के बाहर से सुलभ हैं और इसके साथ आयात किया जा सकता है from <module> import <member>


1
क्या हमें बाज को नहीं छापना चाहिए print(baz())?
जॉन कोल

@ जॉनकोल बाज फंक्शन ऑब्जेक्ट है और बाज () फंक्शन ऑब्जेक्ट चलाएगा
भानु तेज

@ भानुटज बिल्कुल तो print(baz)कुछ प्रिंट करता है <function baz at 0x7f32bc363c10>जबकि print(baz())प्रिंटbaz
जॉन कोल

223

पायथन में __all__ समझाओ?

मैं __all__विभिन्न __init__.pyफाइलों में चर सेट को देखता रहता हूं ।

यह क्या करता है?

क्या करता __all__है?

यह एक मॉड्यूल से शब्दार्थ "सार्वजनिक" नामों की घोषणा करता है। यदि कोई नाम है __all__, तो उपयोगकर्ताओं से इसका उपयोग करने की अपेक्षा की जाती है, और उन्हें यह अपेक्षा हो सकती है कि यह नहीं बदलेगा।

यह भी प्रोग्राम प्रभावित होगा:

import *

__all__एक मॉड्यूल में, जैसे module.py:

__all__ = ['foo', 'Bar']

इसका मतलब है कि जब आप import *मॉड्यूल से आते हैं, तो केवल वे नाम __all__आयात होते हैं:

from module import *               # imports foo and Bar

प्रलेखन उपकरण

दस्तावेज़ीकरण और कोड स्वतः पूर्णता उपकरण (वास्तव में, चाहिए) यह भी __all__निर्धारित करने के लिए निरीक्षण करते हैं कि मॉड्यूल से उपलब्ध नामों को क्या दिखाना है।

__init__.py निर्देशिका को पायथन पैकेज बनाता है

से डॉक्स :

__init__.pyफ़ाइलों अजगर का इलाज के रूप में संकुल युक्त निर्देशिका बनाने के लिए आवश्यक हैं, यह एक सामान्य नाम के साथ निर्देशिकाओं को रोकने के लिए किया जाता है, जैसे कि स्ट्रिंग, अनजाने में वैध मॉड्यूल छिपाते हैं जो बाद में मॉड्यूल खोज पथ पर होते हैं।

सबसे सरल मामले में, __init__.pyबस एक खाली फ़ाइल हो सकती है, लेकिन यह पैकेज के लिए आरंभीकरण कोड निष्पादित कर सकता है या __all__चर सेट कर सकता है।

तो पैकेज__init__.py के __all__लिए घोषणा कर सकते हैं ।

एक एपीआई का प्रबंधन:

एक पैकेज आम तौर पर मॉड्यूल से बना होता है जो एक दूसरे को आयात कर सकता है, लेकिन यह आवश्यक रूप से एक __init__.pyफाइल के साथ एक साथ बंधा हुआ है । वह फ़ाइल वह है जो निर्देशिका को वास्तविक पायथन पैकेज बनाती है। उदाहरण के लिए, कहें कि आपके पास पैकेज में निम्नलिखित फाइलें हैं:

package
├── __init__.py
├── module_1.py
└── module_2.py

चलो पायथन के साथ इन फ़ाइलों को बनाते हैं ताकि आप साथ में पालन कर सकें - आप निम्नलिखित को पायथन 3 शेल में पेस्ट कर सकते हैं:

from pathlib import Path

package = Path('package')
package.mkdir()

(package / '__init__.py').write_text("""
from .module_1 import *
from .module_2 import *
""")

package_module_1 = package / 'module_1.py'
package_module_1.write_text("""
__all__ = ['foo']
imp_detail1 = imp_detail2 = imp_detail3 = None
def foo(): pass
""")

package_module_2 = package / 'module_2.py'
package_module_2.write_text("""
__all__ = ['Bar']
imp_detail1 = imp_detail2 = imp_detail3 = None
class Bar: pass
""")

और अब आपने एक पूर्ण एपीआई प्रस्तुत की है जो आपके पैकेज को आयात करते समय कोई और उपयोग कर सकता है, जैसे:

import package
package.foo()
package.Bar()

और पैकेज में आपके द्वारा उपयोग किए जाने वाले सभी अन्य कार्यान्वयन विवरण नहीं होंगे, जब आपके मॉड्यूल ने packageनाम स्थान को अव्यवस्थित किया ।

__all__ में __init__.py

अधिक काम करने के बाद, शायद आपने तय कर लिया है कि मॉड्यूल बहुत बड़े हैं (कई हजारों लाइनों की तरह?) और विभाजित होने की आवश्यकता है। तो आप निम्न कार्य करें:

package
├── __init__.py
├── module_1
│   ├── foo_implementation.py
│   └── __init__.py
└── module_2
    ├── Bar_implementation.py
    └── __init__.py

सबसे पहले मॉड्यूल के समान नामों के साथ सबपैकेज निर्देशिका बनाएं:

subpackage_1 = package / 'module_1'
subpackage_1.mkdir()
subpackage_2 = package / 'module_2'
subpackage_2.mkdir()

कार्यान्वयन को स्थानांतरित करें:

package_module_1.rename(subpackage_1 / 'foo_implementation.py')
package_module_2.rename(subpackage_2 / 'Bar_implementation.py')

प्रत्येक __init__.pyके __all__लिए घोषणा करने वाले सबपैकेज के लिए s बनाएँ :

(subpackage_1 / '__init__.py').write_text("""
from .foo_implementation import *
__all__ = ['foo']
""")
(subpackage_2 / '__init__.py').write_text("""
from .Bar_implementation import *
__all__ = ['Bar']
""")

और अब आपके पास पैकेज स्तर पर अभी भी एपीआई का प्रावधान है:

>>> import package
>>> package.foo()
>>> package.Bar()
<package.module_2.Bar_implementation.Bar object at 0x7f0c2349d210>

और आप आसानी से अपने एपीआई में उन चीजों को जोड़ सकते हैं जिन्हें आप उप-पैकेज के मॉड्यूल स्तर के बजाय उप-पैकेज स्तर पर प्रबंधित कर सकते हैं। यदि आप एपीआई में एक नया नाम जोड़ना चाहते हैं, तो आप बस __init__.pyमॉड्यूल में उदा।

from .Bar_implementation import *
from .Baz_implementation import *
__all__ = ['Bar', 'Baz']

और यदि आप Bazशीर्ष स्तर एपीआई में प्रकाशित करने के लिए तैयार नहीं हैं , तो अपने शीर्ष स्तर में __init__.pyआप हो सकते हैं:

from .module_1 import *       # also constrained by __all__'s
from .module_2 import *       # in the __init__.py's
__all__ = ['foo', 'Bar']     # further constraining the names advertised

और यदि आपके उपयोगकर्ता इसकी उपलब्धता से अवगत हैं Baz, तो वे इसका उपयोग कर सकते हैं:

import package
package.Baz()

लेकिन अगर वे इसके बारे में नहीं जानते हैं, तो अन्य उपकरण (जैसे pydoc ) उन्हें सूचित नहीं करेंगे।

बाद में Bazप्राइम टाइम के लिए तैयार होने पर आप इसे बदल सकते हैं :

from .module_1 import *
from .module_2 import *
__all__ = ['foo', 'Bar', 'Baz']

उपसर्ग _बनाम __all__:

डिफ़ॉल्ट रूप से, पायथन उन सभी नामों को निर्यात करेगा जो किसी के साथ शुरू नहीं होते हैं _। आप निश्चित रूप से इस तंत्र पर भरोसा कर सकते हैं। पायथन मानक पुस्तकालय में कुछ पैकेज, वास्तव में, इस पर भरोसा करते हैं, लेकिन ऐसा करने के लिए, वे अपने आयातों को उर्फ ​​करते हैं, उदाहरण के लिए ctypes/__init__.py:

import os as _os, sys as _sys

_सम्मेलन का उपयोग करना अधिक सुरुचिपूर्ण हो सकता है क्योंकि यह नामों को फिर से नाम देने की अतिरेक को दूर करता है। लेकिन यह आयातों के लिए अतिरेक जोड़ता है (यदि आपके पास उनमें से बहुत कुछ है) और इसे लगातार करना भूल जाना आसान है - और आखिरी चीज जो आप चाहते हैं वह है अनिश्चित काल के लिए कुछ का समर्थन करना जिसका आप केवल कार्यान्वयन विवरण होना चाहते हैं, बस क्योंकि आप _किसी फ़ंक्शन का नामकरण करते समय उपसर्ग करना भूल गए थे ।

मैं व्यक्तिगत रूप से __all__मॉड्यूल के लिए अपने विकास के जीवन चक्र में एक शुरुआती लिखता हूं ताकि जो लोग मेरे कोड का उपयोग कर सकते हैं वे जान सकें कि उन्हें क्या उपयोग करना चाहिए और क्या नहीं।

मानक पुस्तकालय में अधिकांश पैकेज भी उपयोग करते हैं __all__

जब बचना __all__समझ में आता है

जब इसके _बदले में उपसर्ग सम्मेलन से चिपके रहना समझ में आता है __all__:

  • आप अभी भी शुरुआती विकास मोड में हैं और आपके पास कोई उपयोगकर्ता नहीं है, और लगातार अपने एपीआई को ट्वीक कर रहे हैं।
  • हो सकता है कि आपके पास उपयोगकर्ता हों, लेकिन आपके पास unittests हैं जो API को कवर करते हैं, और आप अभी भी सक्रिय रूप से API में जोड़ रहे हैं और विकास में ट्विक कर रहे हैं।

एक exportडेकोरेटर

उपयोग करने __all__का नकारात्मक पक्ष यह है कि आपको दो बार निर्यात किए जा रहे कार्यों और वर्गों के नाम लिखने होते हैं - और जानकारी को परिभाषाओं से अलग रखा जाता है। हम इस समस्या को हल करने के लिए डेकोरेटर का उपयोग कर सकते हैं।

मुझे पैकेजिंग पर डेविड बेज़ले की बात से इस तरह के एक निर्यात सज्जाकार के लिए विचार मिला। यह कार्यान्वयन सीपीथॉन के पारंपरिक आयातक में अच्छा काम करता है। यदि आपके पास एक विशेष आयात हुक या सिस्टम है, तो मैं इसकी गारंटी नहीं देता, लेकिन यदि आप इसे अपनाते हैं, तो इसे वापस करने के लिए काफी तुच्छ है - आपको केवल नामों को मैन्युअल रूप से वापस जोड़ने की आवश्यकता होगी__all__

इसलिए, उदाहरण के लिए, एक उपयोगिता पुस्तकालय, आप डेकोरेटर को परिभाषित करेंगे:

import sys

def export(fn):
    mod = sys.modules[fn.__module__]
    if hasattr(mod, '__all__'):
        mod.__all__.append(fn.__name__)
    else:
        mod.__all__ = [fn.__name__]
    return fn

और फिर, जहाँ आप परिभाषित करेंगे __all__, आप ऐसा करते हैं:

$ cat > main.py
from lib import export
__all__ = [] # optional - we create a list if __all__ is not there.

@export
def foo(): pass

@export
def bar():
    'bar'

def main():
    print('main')

if __name__ == '__main__':
    main()

और यह ठीक काम करता है कि मुख्य रूप से चलाया जाए या किसी अन्य फ़ंक्शन द्वारा आयात किया जाए।

$ cat > run.py
import main
main.main()

$ python run.py
main

और एपीआई प्रावधान के साथ import *भी काम करेगा:

$ cat > run.py
from main import *
foo()
bar()
main() # expected to error here, not exported

$ python run.py
Traceback (most recent call last):
  File "run.py", line 4, in <module>
    main() # expected to error here, not exported
NameError: name 'main' is not defined

1
क्रॉस संदर्भ: मैंने इस सीडब्ल्यू में आपके डेकोरेटर का उल्लेख इस सवाल के जवाब में किया है कि @exportडेकोरेटर कैसे लिखें ।
MvG

13
यह सबसे उपयोगी उत्तर दम कर दिया गया मैं मदद करने के एक अपेक्षाकृत नए अजगर डेवलपर के साथ मॉड्यूल / संकुल आयात करने की प्रक्रिया को समझने के संबंध में देखा है है __init__.pyऔर के उपयोग__all__
ब्रेट रेइनहार्ड

इससे मुझे बहुत मदद मिलती है। मेरी समस्या, यह है, कि जिन सबमॉड्यूल्स को मैं आयात करना चाहता हूं, वे सभी उत्पन्न फाइलों को अपने प्रतीकों में बहुत सारे cruft के साथ उत्पन्न करते हैं जिन्हें मैं बाहर निकालना चाहता हूं, बिना मैन्युअल रूप से यह सुनिश्चित करने के लिए कि __all__यह सही है।
माइक सी

@ मायके तो शायद आपको __all__भी उत्पन्न करना चाहिए - लेकिन फिर मैं कहूंगा कि आपके पास एक अस्थिर एपीआई है ... यह कुछ व्यापक स्वीकृति परीक्षणों के लिए कुछ होगा।
हारून हॉल

"वे सभी अन्य नामों होगा नहीं ... पैकेज नाम स्थान को अव्यवस्थित" @AaronHall लेकिन वे जाएगा नाम है module_1और module_2; यह एक स्पष्ट शामिल करने के लिए ठीक है del module_1में __init__.py? क्या मैं यह सोचने के लिए गलत हूँ कि यह सार्थक है?
माइक सी

176

मैं इसे सटीक होने के लिए जोड़ रहा हूं:

अन्य सभी उत्तर मॉड्यूल को संदर्भित करते हैं । मूल प्रश्न का स्पष्ट रूप __all__से __init__.pyफाइलों में उल्लेख किया गया है, इसलिए यह अजगर पैकेज के बारे में है

आम तौर पर, __all__केवल तभी खेल में आता है जब कथन के from xxx import *प्रकार का importउपयोग किया जाता है। यह पैकेज के साथ-साथ मॉड्यूल पर भी लागू होता है।

मॉड्यूल के व्यवहार को अन्य उत्तरों में समझाया गया है। संकुल के लिए सटीक व्यवहार यहाँ विस्तार से वर्णित है

संक्षेप में, __all__पैकेज स्तर मॉड्यूल के लिए लगभग एक ही काम करता है, सिवाय इसके कि यह पैकेज के भीतर मॉड्यूल के साथ काम करता है ( मॉड्यूल के भीतर निर्दिष्ट नामों के विपरीत )। इसलिए __all__उन सभी मॉड्यूल्स को निर्दिष्ट करता है जो हमारे द्वारा उपयोग किए जाने पर वर्तमान नामस्थान में लोड और आयात किए जाएंगे from package import *

बड़ा अंतर यह है, कि जब आप किसी पैकेज की घोषणा को छोड़ देते हैं , तो कथन कुछ भी आयात नहीं करेगा (प्रलेखन में वर्णित अपवादों के साथ, ऊपर लिंक देखें)।__all____init__.pyfrom package import *

दूसरी ओर, यदि आप __all__एक मॉड्यूल में छोड़ देते हैं , तो "तारांकित आयात" मॉड्यूल में परिभाषित सभी नामों (एक अंडरस्कोर के साथ शुरू नहीं) को आयात करेगा।


29
from package import *अभी भी परिभाषित सब कुछ आयात करेगा __init__.py, भले ही कोई भी क्यों न हो all। महत्वपूर्ण अंतर यह है कि इसके बिना __all__पैकेज की निर्देशिका में परिभाषित किसी भी मॉड्यूल को स्वचालित रूप से आयात नहीं किया जाएगा।
निकोटियो

जब सभी में [foo, bar] और test.py फ़ाइल में होता है, यदि हम उपयोग करते हैं: पैकेज आयात * से, तो, क्या foo और bar टेस्टोस्टेरोन के स्थानीय नामस्थान में आयात किए जाते हैं या foo और बार में स्वयं के नामस्थान हैं?
चर

87

यह भी बदलता है कि pydoc क्या दिखाएगा:

module1.py

a = "A"
b = "B"
c = "C"

module2.py

__all__ = ['a', 'b']

a = "A"
b = "B"
c = "C"

$ pydoc मॉड्यूल 1

मॉड्यूल मॉड्यूल 1 पर मदद:

नाम
    मॉड्यूल 1

फ़ाइल
    module1.py

DATA 
    a = 'A'
     b = 'B'
     c = 'C'

$ pydoc मॉड्यूल 2

मॉड्यूल मॉड्यूल 2 पर मदद:

नाम
    module2

फ़ाइल
    module2.py

DATA 
    __all__ = ['a', 'b']
     a = 'A'
     b = 'B'

मैं अपने __all__सभी मॉड्यूलों में घोषणा करता हूं, साथ ही आंतरिक विवरणों को भी रेखांकित करता हूं, ये उन चीजों का उपयोग करते समय मदद करते हैं जिन्हें आपने पहले कभी भी लाइव इंटरप्रिटेशन सत्रों में उपयोग नहीं किया है।


54

__all__में अनुकूलित करता *हैfrom <module> import *

__all__में अनुकूलित करता *हैfrom <package> import *


एक मॉड्यूल एक .pyफ़ाइल है जिसे आयात किया जाना है।

एक पैकेज एक __init__.pyफ़ाइल के साथ एक निर्देशिका है । एक पैकेज में आमतौर पर मॉड्यूल होते हैं।


मॉड्यूल

""" cheese.py - an example module """

__all__ = ['swiss', 'cheddar']

swiss = 4.99
cheddar = 3.99
gouda = 10.99

__all__मानव को मॉड्यूल की "सार्वजनिक" विशेषताओं को जानने देता है । [ @AaronHall ] इसके अलावा, pydoc उन्हें पहचानता है। [ @Longpoke ]

से मॉड्यूल आयात *

देखें कि कैसे swissऔर cheddarस्थानीय नामस्थान में लाया जाता है, लेकिन नहीं gouda:

>>> from cheese import *
>>> swiss, cheddar
(4.99, 3.99)
>>> gouda
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'gouda' is not defined

इसके बिना __all__, कोई भी प्रतीक (जो अंडरस्कोर से शुरू नहीं होता) उपलब्ध होता।


इसके बिना आयात *प्रभावित नहीं होता है__all__


आयात मॉड्यूल

>>> import cheese
>>> cheese.swiss, cheese.cheddar, cheese.gouda
(4.99, 3.99, 10.99)

से मॉड्यूल आयात नाम

>>> from cheese import swiss, cheddar, gouda
>>> swiss, cheddar, gouda
(4.99, 3.99, 10.99)

स्थानीय नाम के रूप में आयात मॉड्यूल

>>> import cheese as ch
>>> ch.swiss, ch.cheddar, ch.gouda
(4.99, 3.99, 10.99)

संकुल

पैकेज की __init__.pyफाइल में सार्वजनिक मॉड्यूल या अन्य वस्तुओं के नाम के साथ तार की एक सूची है। वे सुविधाएँ वाइल्डकार्ड आयात के लिए उपलब्ध हैं। मॉड्यूल के साथ, पैकेज से वाइल्डकार्ड-आयात करते समय कस्टमाइज़ करता है । [ @MartinStettner ] __all____all__*

यहाँ पायथन MySQL कनेक्टर से एक अंश है __init__.py:

__all__ = [
    'MySQLConnection', 'Connect', 'custom_error_exception',

    # Some useful constants
    'FieldType', 'FieldFlag', 'ClientFlag', 'CharacterSet', 'RefreshOption',
    'HAVE_CEXT',

    # Error handling
    'Error', 'Warning',

    ...etc...

    ]

पैकेज के लिए नहीं __all__के साथ डिफ़ॉल्ट मामला, तारांकन जटिल है, क्योंकि स्पष्ट व्यवहार महंगा होगा: पैकेज में सभी मॉड्यूल की खोज के लिए फ़ाइल सिस्टम का उपयोग करना। इसके बजाय, डॉक्स के मेरे पढ़ने में, केवल परिभाषित वस्तुओं __init__.pyको आयात किया जाता है:

यदि __all__परिभाषित नहीं किया गया है, तो बयान पैकेज से सभी सबमॉड्यूल को वर्तमान नामस्थान में आयात नहींfrom sound.effects import * करता है ; यह केवल यह सुनिश्चित करता है कि पैकेज आयात किया गया है (संभवतः किसी भी प्रारंभ कोड को चालू कर रहा है ) और फिर पैकेज में जो भी नाम परिभाषित किए गए हैं उन्हें आयात करता है। इसमें कोई भी नाम (और सबमोडुल्स स्पष्ट रूप से भरा हुआ) शामिल है । इसमें पैकेज का कोई सबमॉड्यूल भी शामिल है जिसे पिछले आयात विवरणों द्वारा स्पष्ट रूप से लोड किया गया था।sound.effectssound.effects__init__.py__init__.py


वाइल्डकार्ड आयात ... से बचना चाहिए क्योंकि वे [भ्रमित] पाठक और कई स्वचालित उपकरण हैं।

[ पीईपी 8 , @ टूलमेकरसैटवे]


2
मैं वास्तव में इस उत्तर को पसंद करता हूं, लेकिन मुझे इस बात की जानकारी याद आ रही है कि इसके from <package> import *बिना डिफ़ॉल्ट व्यवहार क्या है, किसी भी मॉड्यूल को आयात नहीं कर रहा है__all____init__.py
राडज़क

धन्यवाद @ जतिमीर, मैंने सबसे अच्छा स्पष्ट किया कि मैं बिना प्रयोगों के दौड़ सकता हूं। मैं लगभग इस मामले को कहना चाहता था (एक पैकेज के लिए सभी के बिना तारांकन) एक व्यवहार करता है जैसे कि __init__.pyएक मॉड्यूल था । लेकिन मुझे यकीन नहीं है कि यह सटीक है, या विशेष रूप से यदि अंडरस्कोर-उपसर्गित वस्तुओं को बाहर रखा गया है। इसके अलावा, मैंने मॉड्यूल और पैकेज पर वर्गों को और अधिक स्पष्ट रूप से अलग कर दिया है। तुम्हारे विचार?
बॉब स्टीन

49

से (एक अनौपचारिक) पायथन संदर्भ विकी :

एक मॉड्यूल द्वारा परिभाषित सार्वजनिक नाम एक चर नाम के लिए मॉड्यूल के नाम स्थान की जांच करके निर्धारित किए जाते हैं __all__; यदि परिभाषित किया गया है, तो यह उन तारों का एक अनुक्रम होना चाहिए, जो उस मॉड्यूल द्वारा परिभाषित या आयातित नाम हैं। जिन नामों को दिया गया है, __all__वे सभी सार्वजनिक माने जाते हैं और उनका अस्तित्व होना आवश्यक है। यदि __all__परिभाषित नहीं किया गया है, तो सार्वजनिक नामों के सेट में मॉड्यूल के नामस्थान में पाए जाने वाले सभी नाम शामिल हैं जो अंडरस्कोर वर्ण ("_") से शुरू नहीं होते हैं। __all__संपूर्ण सार्वजनिक API होना चाहिए। यह गलती से निर्यात की जाने वाली वस्तुओं से बचने का इरादा है जो एपीआई का हिस्सा नहीं हैं (जैसे पुस्तकालय मॉड्यूल जो आयात किए गए थे और मॉड्यूल के भीतर उपयोग किए गए थे)।


सूचीबद्ध लिंक मृत है। लेकिन vdocuments.net// पर टेक्स्ट वर्बेटिम मिला और यहाँ: dokumen.tips/documents/reference-567bab8d6118a.html
JayRizzo

8

__all__इसका उपयोग पायथन मॉड्यूल के सार्वजनिक एपीआई के दस्तावेज के लिए किया जाता है। हालांकि यह वैकल्पिक है, __all__इसका उपयोग किया जाना चाहिए।

यहाँ पाइथन भाषा के संदर्भ से संबंधित अंश प्रस्तुत है :

एक मॉड्यूल द्वारा परिभाषित सार्वजनिक नाम एक चर नाम के लिए मॉड्यूल के नाम स्थान की जांच करके निर्धारित किए जाते हैं __all__; यदि परिभाषित किया गया है, तो यह उन तारों का एक अनुक्रम होना चाहिए, जो उस मॉड्यूल द्वारा परिभाषित या आयातित नाम हैं। जिन नामों को दिया गया है, __all__वे सभी सार्वजनिक माने जाते हैं और उनका अस्तित्व होना आवश्यक है। यदि __all__परिभाषित नहीं किया गया है, तो सार्वजनिक नामों के सेट में मॉड्यूल के नामस्थान में पाए जाने वाले सभी नाम शामिल हैं जो अंडरस्कोर वर्ण ('_') से शुरू नहीं होते हैं। __all__संपूर्ण सार्वजनिक API होना चाहिए। यह गलती से निर्यात की जाने वाली वस्तुओं से बचने का इरादा है जो एपीआई का हिस्सा नहीं हैं (जैसे पुस्तकालय मॉड्यूल जो आयात किए गए थे और मॉड्यूल के भीतर उपयोग किए गए थे)।

PEP 8 इसी तरह के शब्दों का उपयोग करता है, हालांकि यह भी स्पष्ट करता है कि __all__अनुपस्थित होने पर आयातित नाम सार्वजनिक API का हिस्सा नहीं हैं:

आत्मनिरीक्षण का बेहतर समर्थन करने के लिए, मॉड्यूल को स्पष्ट रूप से __all__विशेषता का उपयोग करके अपने सार्वजनिक एपीआई में नामों की घोषणा करनी चाहिए । __all__खाली सूची पर सेट करना दर्शाता है कि मॉड्यूल में कोई सार्वजनिक एपीआई नहीं है।

[...]

आयातित नामों को हमेशा एक कार्यान्वयन विवरण माना जाना चाहिए। अन्य मॉड्यूल को ऐसे आयातित नामों के अप्रत्यक्ष उपयोग पर भरोसा नहीं करना चाहिए जब तक कि वे मॉड्यूल के एपीआई युक्त एक स्पष्ट रूप से प्रलेखित हिस्सा नहीं हैं, जैसे कि os.pathया एक पैकेज का __init__मॉड्यूल जो सबमॉड्यूल से कार्यक्षमता को उजागर करता है।

इसके अलावा, जैसा कि अन्य उत्तरों में बताया गया है, पैकेज के लिए आयात होने वाले वाइल्डकार्ड__all__ को सक्षम करने के लिए उपयोग किया जाता है :

आयात विवरण निम्न सम्मेलन का उपयोग करता है: यदि पैकेज का __init__.pyकोड नाम की सूची को परिभाषित करता है __all__, तो इसे मॉड्यूल नामों की सूची के रूप में लिया जाता है, जिनका from package import *सामना होने पर आयात किया जाना चाहिए ।


8

संक्षिप्त जवाब

__all__from <module> import *बयानों को प्रभावित करता है।

लंबा जवाब

इस उदाहरण पर विचार करें:

foo
├── bar.py
└── __init__.py

इन foo/__init__.py:

  • (लागू) यदि हम परिभाषित नहीं करते हैं __all__, तो from foo import *केवल परिभाषित नाम आयात करेंगे foo/__init__.py

  • (स्पष्ट) यदि हम परिभाषित करते हैं __all__ = [], तो from foo import *कुछ भी आयात नहीं करेगा।

  • (स्पष्ट) यदि हम परिभाषित करते हैं __all__ = [ <name1>, ... ], तो from foo import *केवल उन नामों को आयात करेंगे।

ध्यान दें कि निहित मामले में, अजगर शुरू होने वाले नामों को आयात नहीं करेगा _। हालाँकि, आप ऐसे नामों का उपयोग करने के लिए बाध्य कर सकते हैं __all__

आप यहां पायथन दस्तावेज़ देख सकते हैं


5

__all__कैसे from foo import *काम करता है प्रभावित करता है।

कोड जो एक मॉड्यूल बॉडी के अंदर है (लेकिन किसी फ़ंक्शन या क्लास के शरीर में नहीं *) एक fromकथन में तारांकन चिह्न ( ) का उपयोग कर सकता है :

from foo import *

*अनुरोध है कि सभी मॉड्यूल के गुण foo(अंडरस्कोर के साथ उन लोगों शुरुआत को छोड़कर) का आयात मॉड्यूल में वैश्विक चर के रूप बाध्य होने के। जब fooएक विशेषता होती है __all__, तो विशेषता का मूल्य उन नामों की सूची है जो इस प्रकार के fromबयान से बंधे हैं ।

यदि fooएक पैकेज है और इसके __init__.pyनाम की सूची को परिभाषित करता है __all__, तो इसे सबमॉड्यूल नामों की सूची के रूप में लिया जाता है जिन्हें from foo import *सामना करने पर आयात किया जाना चाहिए । यदि __all__परिभाषित नहीं किया गया है, तो बयान from foo import *जो भी नाम पैकेज में परिभाषित किया गया है, आयात करता है। इसमें कोई भी नाम (और सबमोडुल्स स्पष्ट रूप से भरा हुआ) शामिल है __init__.py

ध्यान दें कि __all__एक सूची नहीं है। importविवरण पर दस्तावेज के अनुसार , यदि परिभाषित किया गया है, तो स्ट्रिंग्स का__all__ एक क्रम होना चाहिए जो कि मॉड्यूल द्वारा परिभाषित या आयात किए गए नाम हैं। तो आप कुछ मेमोरी और सीपीयू साइकल को बचाने के लिए एक टपल का उपयोग कर सकते हैं । यदि मॉड्यूल किसी एकल सार्वजनिक नाम को परिभाषित करता है तो बस एक अल्पविराम न भूलें:

__all__ = ('some_name',)

यह भी देखें कि "आयात *" बुरा क्यों है?


1

इसे यहाँ PEP8 में परिभाषित किया गया है :

वैश्विक चर नाम

(चलो आशा करते हैं कि ये चर केवल एक मॉड्यूल के अंदर उपयोग के लिए हैं।) कन्वेंशन उन कार्यों के लिए समान हैं।

मॉड्यूल जिनके माध्यम से उपयोग के लिए डिज़ाइन किए गए हैं , उन्हें ग्लोबल्स के निर्यात को रोकने के from M import *लिए __all__तंत्र का उपयोग करना चाहिए , या अंडरस्कोर के साथ ऐसे ग्लोबल्स को प्रीफ़िक्स करने के पुराने सम्मेलन का उपयोग करना चाहिए (जो कि आप इन ग्लोबल्स को इंगित करने के लिए करना चाहते हैं "मॉड्यूल गैर-सार्वजनिक हैं)।"

PEP8 पायथन कोड के लिए कोडिंग कन्वेंशन प्रदान करता है जिसमें मुख्य पायथन वितरण में मानक पुस्तकालय शामिल है। जितना अधिक आप इसका अनुसरण करते हैं, आप मूल इरादे के करीब हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.