5 ответов:
Это список общедоступных объектов этого модуля, как интерпретируется
import *. Он переопределяет значение по умолчанию, скрывающее все, что начинается с подчеркивания.
связанный, но явно не упомянутый здесь, именно тогда, когда есть. Это список строк, определяющих, какие символы в модуле будут экспортированы, когда
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/3.5/tutorial/modules.html#importing-from-a-package
Примечание:
__all__влияет
я просто добавляю это, чтобы быть точным:
все остальные ответы относятся к модули. Исходный вопрос явно упоминается
__all__на__init__.pyфайлы, так что это о python пакетов.как правило,
__all__только вступает в игру, когдаfrom xxx import *вариант утверждение. Это относится как к пакетам, так и к модулям.поведение модулей объясняется в других ответах. Этот точное поведение для пакетов описано здесь подробнее.
короче,
__all__на уровне пакета делает примерно то же самое, что и для модулей, за исключением того, что он имеет дело с модули внутри пакета (в отличие от указания имена в модуле). Так что__all__указывает все модули, которые должны быть загружены и импортированы в текущее пространство имен при использованииfrom package import *.большая разница в том, что когда вы пропустить декларация
__all__в пакете__init__.py, заявлениеfrom package import *не будет импортировать ничего вообще (с исключениями, описанными в документации, см. ссылку выше).С другой стороны, если не указывать
__all__в модуле "звездный импорт" будет импортировать все имена (не начиная с подчеркивания), определенные в модуле.
объясните _ _ все_ _ в Python?
я продолжаю видеть переменной
__all__установить в разных__init__.pyфайлы.что это значит?
что значит
__all__делать?он объявляет семантически "публичные" имена из модуля. Если есть имя в
__all__пользователи должны использовать его, и они могут иметь надежды, что он не изменится.он также будет иметь программные эффекты:
import *
__all__в модуле, например,module.py:__all__ = ['foo', 'Bar']означает, что когда вы
import *из модуля, только эти имена в__all__импортированы:from module import * # imports foo and Barинструменты документирования
инструменты автозаполнения документации и кода могут (фактически, должны) также проверять
__all__чтобы определить, какие имена, чтобы показать, как можно из модуля.
__init__.pyделает a каталог пакета Pythonс docs:
The
__init__.pyфайлы необходимы для того, чтобы Python рассматривал каталоги как содержащие пакеты; это делается для предотвращения непреднамеренного скрытия допустимых модулей, которые встречаются позже в пути поиска модуля, в каталогах с общим именем, например string.в простейшем случае
__init__.pyможет быть просто пустой файл, но он также может выполнять код инициализации упакуйте или установите__all__переменной.так
__init__.pyможет объявить__all__на пакета.управление API:
пакет обычно состоит из модулей, которые могут импортировать друг друга, но которые обязательно связаны вместе с . Этот файл-это то, что делает каталог фактическим пакетом Python. Например, скажем, у вас есть следующее:
package/ |-__init__.py # makes directory a Python package |-module_1.py |-module_2.pyна
__init__.pyвы напишите:from module_1 import * from module_2 import *и
module_1у вас есть:__all__ = ['foo',]и
module_2у вас есть:__all__ = ['Bar',]и теперь вы представили полный api, который кто-то другой может использовать при импорте вашего пакета, например:
import package package.foo() package.Bar()и у них не будет всех других имен, которые вы использовали при создании своих модулей, загромождающих
packageпространство имен.
__all__in__init__.pyпосле дополнительной работы, может быть, у вас есть решил, что модули слишком большие и их нужно разбить. Поэтому вы делаете следующее:
package/ |-__init__.py |-module_1/ | |-__init__.py | |-foo_implementation.py |-module_2/ |-__init__.py |-Bar_implementation.pyи в каждом
__init__.pyобъявлении__all__, например, в module_1:from foo_implementation import * __all__ = ['foo']и module_2 в
__init__.py:from Bar_implementation import * __all__ = ['Bar']и вы можете легко добавить в свой API то, что вы можете управлять на уровне подпакета вместо уровня модуля подпакета. Если вы хотите добавить новое имя в 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']начинаются
_и__all__:по умолчанию Python экспортирует все имена, которые не начинаются с
_. Ты конечно может полагаться на этот механизм. Некоторые пакеты в стандартной библиотеке Python, по сути, do полагайтесь на это, но для этого они псевдонимы их импорта, например, вctypes/__init__.py:import os as _os, sys as _sysс помощью
_конвенция может быть более элегантным потому что это устраняет избыточность именования имен снова. Но он добавляет избыточность для импорта (если у вас их много) и это легко чтобы забыть сделать это последовательно - и последнее, что вы хотите, чтобы бесконечно поддерживать то, что вы намеревались быть только деталь реализации, только потому, что вы забыли префикс_при вводе имени функции.я лично пишу
__all__в начале моего жизненного цикла разработки для модулей, так что другие, кто может использовать мой код, знают, что они должны использовать и не использовать.большинство пакетов в стандартной библиотеке также использовать
__all__.во избежание
__all__смыслимеет смысл придерживаться
_префикс конвенции вместо__all__когда:
- вы все еще находитесь в режиме ранней разработки и не имеете пользователей, и постоянно настраиваете свой API.
- может быть, у вас есть пользователи, но у вас есть unittests, которые охватывают API, и вы все еще активно добавляете в API и настраиваете в разработке.
An
exportоформителяобратная сторона использования
__all__это то, что вы должны написать имена функций и классов, экспортируемых дважды - и информация хранится отдельно от определений. Мы может использовать декоратор для решения этой проблемы.я получил идею для такого декоратора экспорта от Дэвида Разговор Бизли о упаковке. Эта реализация, похоже, хорошо работает в традиционном импортере CPython. Если у вас есть специальный крюк импорта или система, я не гарантирую это, но если вы его примете, довольно тривиально отступить - вам просто нужно вручную добавить имена обратно в
__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и API provisioning с
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
Он также изменяет то, что pydoc покажет:
module1.py
a = "A" b = "B" c = "C"module2.py
__all__ = ['a', 'b'] a = "A" b = "B" c = "C"$ pydoc module1
Help on module module1: NAME module1 FILE module1.py DATA a = 'A' b = 'B' c = 'C'$ pydoc module2
Help on module module2: NAME module2 FILE module2.py DATA __all__ = ['a', 'b'] a = 'A' b = 'B'Я объявляю
__all__во всех моих модулях, а также подчеркивание внутренних деталей, это действительно помогает при использовании вещей, которые вы никогда не использовали раньше в сеансах live interpreter.
Comments