sourcecode

__all_은 Python에서 무엇을 의미합니까?

copyscript 2022. 12. 6. 22:07
반응형

__all_은 Python에서 무엇을 의미합니까?

, .__all____init__.py들들. 게게??

연결은 언제가 될 것인가 것입니다.__all__사용됩니다.이것은 모듈의 어떤 기호를 내보낼지 정의하는 문자열 목록입니다.from <module> import *을 사용하다

를 들어, in, 음음의 입니다.foo.pybar ★★★★★★★★★★★★★★★★★」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 *는 밑줄로 시작하지 않는 모든 기호를 지정된 네임스페이스에서 Import하는 것입니다.

참고 자료: https://docs.python.org/tutorial/modules.html#importing-from-a-package

__all__을 주다from <module> import * 않은 __all__는 모듈 수 Import를 사용하여 수 있습니다.from <module> import <member>.

이 리스트는import * 하는 모든 설정보다 밑줄로 시작하는 모든 것을 숨기는 기본 설정보다 우선됩니다.

모두 Python으로 설명하시겠습니까?

가 계속 .__all__ 곳에 __init__.pyfiles.complete files files files files files files files files.

이게 뭘 하는 거지?

무인 does does 가 뭐죠?__all__ 할수 수 do do do?

모듈로부터 의미론적으로 "퍼블릭" 이름을 선언합니다. __all__사용자는 그것을 사용할 것으로 예상되며 변경되지 않을 것으로 예상할 수 있습니다.

프로그램 효과도 있습니다.

import *

__all__모듈에서는 " " " " " "와 같이 입력합니다.module.py:

__all__ = ['foo', 'Bar']

, ,을 때, 신을 때import *""에 __all__Import 상 :

from module import *               # imports foo and Bar

문서 도구

__all__모듈에서 사용할 수 있는 이름을 결정합니다.

__init__.py를 Python .

문서에서:

__init__.py파일들은 Python이 디렉토리를 패키지를 포함하는 것으로 취급하기 위해 필요합니다.이것은 문자열과 같은 공통 이름을 가진 디렉토리가 모듈 검색 경로에서 나중에 발생하는 유효한 모듈을 의도하지 않게 숨기는 것을 방지하기 위해서입니다.

경우, "는 다음과 같습니다.__init__.py는 빈 파일일 하거나 ""를 도 있습니다.__all__★★★★★★ 。

그...__init__.py할 수 __all__패키지용입니다.

API 관리:

수 되어 있는 모듈로 됩니다.__init__.pyPython을 소개합니다.예를 들어 다음과 같은 파일이 패키지에 있다고 가정합니다.

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

다음 파일을 Python 3 쉘에 붙여넣을 수 있도록 Python으로 작성합시다.

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할 때 사용할 수 있는 완전한 api를 제시했습니다.

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__ 추가:

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

패키지 레벨로 프로비저닝된 api가 아직 남아 있습니다.

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

또한 서브패키지의 모듈레벨 대신 서브패키지레벨로 관리할 수 있는 것을 API에 쉽게 추가할 수 있습니다.할 경우 만 하면 .__init__.py (예: module_2:

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

Baz에서 '''API'''__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']

「」_vs 대 __all__:

Python은 "Python"으로 이름을 ._Import와 함께 import *의 셸 알 수 「 」는 「 」입니다import *은 안 거예요._us_non_public에서 따온 us.py★★★★

$ cat us.py
USALLCAPS = "all caps"
us_snake_case = "snake_case"
_us_non_public = "shouldn't import"
$ python
Python 3.10.0 (default, Oct  4 2021, 17:55:55) [GCC 10.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from us import *
>>> dir()
['USALLCAPS', '__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'us_snake_case']

메커니즘은 확실히 신뢰할 수 있습니다.Python 표준 라이브러리의 일부 패키지는 실제로 이 기능에 의존하지만, 이를 위해 에서와 같이 Import에 별칭을 붙입니다.

import os as _os, sys as _sys

「 」의 _규칙을 사용하면 이름을 다시 명명하는 중복이 제거되므로 보다 우아할 수 있습니다.그러나 Import를 위한 용장성이 추가되어 (많은 경우) 일관되게 이 작업을 수행하는 것을 잊기 쉽습니다.또한 구현 세부사항으로만 의도한 내용을 무기한으로 지원하는 것은 결코 바람직하지 않습니다.단, 이 작업은 단순히 prefix를 붙이는 것을 잊었기 때문입니다._이치

는 으로 ★★★★★★★★★★★★★★★★★★★★를 쓰고 있습니다.__all__모듈 개발 라이프 사이클 초기에 내 코드를 사용할 수 있는 다른 사용자가 모듈을 사용해야 하는 것과 사용하지 말아야 하는 것을 알 수 있도록 합니다.

도 ""를 사용합니다.__all__.

할 때__all__에 맞다

말을 ._「」 에 __all__ adda empty:

  • 아직 초기 개발 모드에 있고 사용자가 없으며 API를 계속 수정하고 있습니다.
  • 사용자가 있을 수 있지만 API를 다루는 unittests를 가지고 있으며, 여전히 API에 적극적으로 추가하고 개발 중에 조정하고 있습니다.

export

「」를 하는 것의 __all__내보낼 함수 및 클래스의 이름을 두 번 써야 하며, 이 정보는 정의와 별도로 유지됩니다.우리는 이 문제를 해결하기 위해 장식가를 사용할 수 있다.

나는 데이비드 비즐리의 포장에 관한 강연에서 그런 수출 장식가의 아이디어를 얻었다.이 구현은 CPython의 전통적인 수입업체에서 잘 작동하는 것으로 보입니다. 「Import」에 「Import」의 「Import」의 「Import」의 「Import」의 「Import」의 「Import」의 「Import」의 「Import」에 되돌리기만 하면 됩니다.수동으로 이름을 다시 추가해야 합니다.__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()

메인 실행이든 다른 함수로 Import하든 상관없습니다.

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

$ python run.py
main

API를 사용한API 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

정확히 말씀드리기 위해 추가하겠습니다.

다른 모든 답변은 모듈에 관한 입니다.처음에 설명했던 질문은__all____init__.pypython 패키지에 대한 내용입니다.

「일부러」__all__ 동작하는 것은, 「 」의 뿐입니다.from xxx import *import스테이트먼트가 사용됩니다.이는 모듈뿐만 아니라 패키지에도 적용됩니다.

모듈의 동작은 다른 답변에 설명되어 있습니다.패키지의 정확한 동작은 여기에 자세히 설명되어 있습니다.

로 말하면, 요,,,__all__패키지 레벨에서는 (모듈 내의 이름을 지정하는 것과는 대조적으로) 패키지 내의 모듈을 취급하는 것을 제외하고 모듈에서의 동작과 거의 동일합니다.그렇게__all__ 、 [ Import ]를 사용할 때 합니다.from package import *.

가장 큰 차이점은, 선언을 생략했을 때__all__꾸 a __init__.py 「 「 」라고 하는 문.from package import *는 아무것도 Import하지 않습니다(단, 매뉴얼에 설명되어 있는 예외는 위의 링크를 참조).

ㅇㅇ를 하면 ㅇㅇㅇㅇ가 됩니다.__all__모듈에서는 "internal import"에 의해 모듈에 정의된 모든 이름(밑줄로 시작하지 않음)이 Import됩니다.

또한 pydoc에 표시되는 내용도 변경됩니다.

module1.화이

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

모듈 2화이

__all__ = ['a', 'b']

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

$pydoc module 1

모듈 1 도움말:

이름모듈 1
파일module1.화이
데이터a = 'A'b = 'B'c = 'C'

$pydoc module 2

모듈 2 도움말:

이름모듈 2
파일모듈 2화이
데이터__all__ = ['a', 'b']a = 'A'b = 'B'

__all__모든 모듈 및 내부 세부사항에 밑줄을 그으면 라이브 인터프리터 세션에서 사용하지 않은 것을 사용할 때 매우 도움이 됩니다.

__all__를 커스터마이즈 합니다.*및 에 있습니다.


모듈은.py수입하다.

패키지는, 다음의 디렉토리입니다.__init__.py을. 을. 을. 을. 을. 을. 을. 을. 을. 을. 을. 을. 을. 을. 을. 을. 을. 을. 을. 을. 을.을.


모듈

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

__all__ = ['swiss', 'cheddar']

swiss = 4.99
cheddar = 3.99
gouda = 10.99

__all__모듈의 "[@AaronHall]퍼블릭" 기능을 사용자에게 알려줍니다.또한 pydoc이 그들을 [@Longpoke]알아봅니다.

모듈 Import에서*

것은 이쪽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__하지 않는 기호도 할 수


★★Import를 사용하지 *을 받지 않다__all__


Import 모듈

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

모듈 Import 이름에서

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

로컬명으로 모듈 Import

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

패키지

서서 __init__.py소포를 정리하다 __all__는 퍼블릭 모듈 또는 기타 객체의 이름을 가진 문자열 목록입니다.수입하다로, 「」는, 「」__all__ *패키지에서 [@MartinStettner]와일드카드가 검출되었을 경우.

다음은 Python MySQL Connector에서 발췌한 것입니다. __init__.py:

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

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

    # Error handling
    'Error', 'Warning',

    ...etc...

    ]

패키지 의 모든 모듈을 검색하기 위해 파일시스템을 사용하는 경우라는 명백한 동작에 비용이 많이 들기 때문에 기본 대소문자인 아스타리스크는 복잡합니다.대신, 제가 읽은 문서에서는__init__.pyImport 상 :

if__all__ 않습니다.이 정의되어 있지 않습니다.from sound.effects import *패키지에서 일부 하위 모듈을 Import하지 않음sound.effects네임스페이스로 만, 할 수 있는 것은, 「패키지」입니다.패키지가sound.effectsImport되었습니다(Import의 를 실행하고 있을 가능성이 ).__init__.py그런 다음 패키지에 정의된 이름을 가져옵니다.에는 "Submodules및 )에 의해 된 이름이 됩니다.__init__.py또한 이전 Import 스테이트먼트에 의해 명시적으로 로드된 패키지의 서브모듈도 포함됩니다.


그리고 마지막으로, 스택 오버플로 답변, 교수 및 맨스플라이너에 대한 존경받는 전통은 애초에 질문을 한 것에 대한 비난의 본질이 됩니다.

와일드카드 가져오기...리더와 많은 자동화 툴이 [비밀]되어 있으므로 피해야 합니다.

[PEP 8, @Toolmaker Steve]

단답

__all__을 주다from <module> import *★★★★★★★★★★★★★★★★★★.

장답

다음 예를 생각해 보겠습니다.

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

»foo/__init__.py:

  • __all__ , , , 「 」from foo import *는 Import에 .foo/__init__.py.

  • 을 하는 __all__ = [] , , , 「 」from foo import *수입하다

  • 을 하는 __all__ = [ <name1>, ... ] , , , 「 」from foo import *수입하다

은 python으로 _Import를 사용하면 이러한 수 __all__.

여기서 Python 문서를 볼 수 있습니다.

__all__Python API입니다.만, 「 。__all__사용해야 합니다.

다음은 Python 언어 참조에서 발췌한 것입니다.

하여 됩니다.__all__; 정의되어 있는 경우 해당 모듈에 의해 정의되거나 Import된 일련의 문자열이어야 합니다. 이름__all__모두 공개로 간주되어 존재해야 합니다. if__all__정의되어 있지 않습니다.공용 이름 집합에는 밑줄 문자('_')로 시작하지 않는 모듈의 네임스페이스에서 발견된 모든 이름이 포함됩니다. __all__API를 사용합니다.API의 일부가 아닌 항목(모듈 내에서 Import되어 사용된 라이브러리 모듈 등)을 실수로 내보내는 것을 방지하기 위한 것입니다.

PEP 8은 유사한 표현을 사용하지만 Import된 이름이 퍼블릭 API의 일부가 아님을 명확히 합니다.__all__존재하지 않습니다.

보다 은 Introspection의 Public API를 .__all__설정하다__all__에 퍼블릭 to empty list가 .

[...]

Import된 이름은 항상 구현 세부사항으로 간주해야 합니다.다른 중 한를 들어, 「」 「API」 「 Import 」 등입니다.os.path의 「」를 참조해 주세요.__init__서브모듈에서 기능을 제공하는 모듈입니다.

되듯이 '하다'라는 표현도 있습니다__all__는 패키지의 와일드카드 Import를 활성화하기 위해 사용됩니다.

되어 다음의 표기법을 합니다.패키지가__init__.py는 code라는 이름의 합니다.__all__ 、 [ Import ]에 Import 할 때 from package import *을 사용하다

__all__ 을 주다from foo import *

본문 내에 코드)는 아스타리스크(「」)를할 수 .*)에서는from★★★★★★★★

from foo import *

* Atribute의 됩니다.foo(밑줄로 시작하는 변수 제외)는 Import 모듈에서 글로벌 변수로 바인드됩니다.foo.__all__은 Atribute, Atribute, Atribute, Atribute의 이 유형에 의해 from★★★★★★ 。

iffoo패키지 및 그__init__.py, 「을합니다.__all__는, 다음의 경우에 Import 할 필요가 있는 서브 모듈명의 리스트로 간주됩니다.from foo import *을 사용하다 if__all__ 않습니다.이 정의되어 있지 않습니다.from foo import *수입하다에는 "Submodules및 )에 의해 된 이름이 됩니다.__init__.py.

:__all__목록이 될 필요는 없습니다.스테이트먼트에 기재되어 있는 문서에 따라 정의되어 있는 경우,__all__는 모듈에 의해 정의되거나 Import된 일련의 문자열이어야 합니다.따라서 태플을 사용하여 메모리와 CPU 사이클을 절약할 수 있습니다.모듈이 단일 공용 이름을 정의하는 경우 쉼표를 잊지 마십시오.

__all__ = ('some_name',)

참고 항목: "import *"가 나쁜 이유는 무엇입니까?

이것은, 다음의 PEP8 에 정의되어 있습니다.

글로벌 변수 이름

(이러한 변수는 1개의 모듈 내에서만 사용할 수 있도록 합니다).표기법은 기능에 관한 표기법과 거의 동일합니다.

를 통해 from M import * 해야 요.__all__글로벌 내보내기를 방지하거나 이러한 글로벌 앞에 언더스코어를 붙이는 오래된 규칙을 사용하는 메커니즘입니다(이러한 글로벌이 "비공개"임을 나타내기 위해 수행할 수 있습니다).

PEP8은 기본 Python 배포판의 표준 라이브러리를 구성하는 Python 코드에 대한 코딩 규칙을 제공합니다.이것을 따라갈수록, 당신은 원래의 의도에 더 가까워진다.

언급URL : https://stackoverflow.com/questions/44834/what-does-all-mean-in-python

반응형