Я использую Python все больше и больше и продолжаю видеть переменную __all__, установленную в разных файлах __init__.py. Может кто-нибудь объяснить, что это значит?






Это список общедоступных объектов этого модуля в интерпретации import *. Он отменяет стандартное скрытие всего, что начинается с подчеркивания.
@BrandonRhodes: это тоже не совсем так: рекомендуется импортировать только те модули, которые, как вы знаете, предназначены для import * (например, tk). Хороший намек в этом случае - наличие __all__ или имен, начинающихся с подчеркивания в коде модуля.
Общедоступные и внутренние интерфейсы - python.org/dev/peps/pep-0008/#id50. Чтобы лучше поддерживать самоанализ, модули должны явно объявлять имена в своем общедоступном API с помощью атрибута __all__. Установка __all__ в пустой список означает, что у модуля нет общедоступного API.
Я не уверен, что если бы tk был выпущен сегодня (или даже в 2012 году), рекомендуемой практикой было бы использование from tk import *. Я думаю, что такая практика принята по инерции, а не намеренно.
От (Неофициальный) Справочник по Python вики:
The public names defined by a module are determined by checking the module's namespace for a variable named
__all__; if defined, it must be a sequence of strings which are names defined or imported by that module. The names given in__all__are all considered public and are required to exist. If__all__is not defined, the set of public names includes all names found in the module's namespace which do not begin with an underscore character ("_").__all__should contain the entire public API. It is intended to avoid accidentally exporting items that are not part of the API (such as library modules which were imported and used within the module).
Указанная ссылка мертва. но нашел дословный текст на vdocuments.net/… и здесь: dokumen.tips/documents/reference-567bab8d6118a.html
Связано, но не упомянуто здесь явно, когда используется __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>.
разве мы не должны печатать baz как print(baz())?
@JohnCole baz - это функциональный объект, а baz () запускает функциональный объект.
@BhanuTez именно так. Итак, print(baz) печатает что-то вроде <function baz at 0x7f32bc363c10>, тогда как print(baz()) печатает baz.
Цель состоит в том, чтобы проиллюстрировать, что символы экспортируются. Выполняет он функцию или нет - вторично.
Меня озадачивает то, что до сих пор нет способа заполнить __all__, напрямую ссылаясь на функции / объекты. Вместо этого мы должны вводить их имена и исправлять их индивидуально каждый раз, когда имя меняется. Кажется, очень подвержен ошибкам для активных кодовых баз.
@JulioCezarSilva немного не по теме, но стоит отметить, что для классов и функций вы можете использовать свойство __name__
Это также меняет то, что покажет 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
DATAa = '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__ во всех своих модулях, а также подчеркиваю внутренние детали, они действительно помогают при использовании вещей, которые вы никогда раньше не использовали в сеансах реального интерпретатора.
Я просто добавляю это, чтобы быть точным:
Все остальные ответы относятся к модули. В исходном вопросе явно упоминается __all__ в файлах __init__.py, поэтому речь идет о python пакеты.
Как правило, __all__ вступает в игру только тогда, когда используется вариант from xxx import * оператора import. Это относится как к пакетам, так и к модулям.
Поведение модулей объясняется в других ответах. Точное поведение пакетов подробно описано здесь.
Короче говоря, __all__ на уровне пакета делает примерно то же самое, что и для модулей, за исключением того, что он имеет дело с модули в пакете (в отличие от указания имена в модуле). Таким образом, __all__ определяет все модули, которые должны быть загружены и импортированы в текущее пространство имен при использовании from package import *.
Большая разница в том, что когда вы пропускать декларируете __all__ в пакете __init__.py, инструкция from package import * вообще ничего не импортирует (за исключениями, описанными в документации, см. Ссылку выше).
С другой стороны, если вы опустите __all__ в модуле, «помеченный импорт» импортирует все имена (не начинающиеся с подчеркивания), определенные в модуле.
from package import * по-прежнему будет импортировать все, что определено в __init__.py, даже если нет all. Важное отличие состоит в том, что без __all__ он не будет автоматически импортировать модули, определенные в каталоге пакета.
Когда все содержит [foo, bar] и в файле test.py, если мы используем: from package import *, то импортируются ли foo и bar в локальное пространство имен test.py или в собственное пространство имен foo и bars?
__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 распознает их.
Посмотрите, как 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упаковка__all__ находится список строк с именами общедоступных модулей или других объектов. Эти функции доступны для импорта с подстановочными знаками. Как и в случае с модулями, __all__ настраивает * при импорте подстановочных знаков из пакета.
Вот выдержка из Соединитель Python 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:
If
__all__is not defined, the statementfrom sound.effects import *does not import all submodules from the packagesound.effectsinto the current namespace; it only ensures that the packagesound.effectshas been imported (possibly running any initialization code in__init__.py) and then imports whatever names are defined in the package. This includes any names defined (and submodules explicitly loaded) by__init__.py. It also includes any submodules of the package that were explicitly loaded by previous import statements.
И, наконец, почитаемая традиция ответов на вопросы о переполнении стека, профессоров и специалистов по всему миру - это упрек Bon Mot за то, что они задают вопрос в первую очередь:
Wildcard imports ... should be avoided, as they [confuse] readers and many automated tools.
Мне очень нравится этот ответ, но мне не хватает информации о том, какое поведение по умолчанию для from <package> import * без __all__ в __init__.py, то есть не импортировать ни один из модулей.
Спасибо @Jatimir, я как мог уточнил, не проводя экспериментов. Я почти хотел сказать, что этот случай (звездочка без всего для пакета) ведет себя так же как если бы __init__.py был модулем. Но я не уверен, что это правильно, или, в частности, исключены ли объекты с префиксом подчеркивания. Также я более четко разделил разделы на МОДУЛИ и ПАКЕТЫ. Твои мысли?
__all__ используется для документирования общедоступного API модуля Python. Хотя это необязательно, следует использовать __all__.
Вот соответствующий отрывок из справочник по языку Python:
The public names defined by a module are determined by checking the module’s namespace for a variable named
__all__; if defined, it must be a sequence of strings which are names defined or imported by that module. The names given in__all__are all considered public and are required to exist. If__all__is not defined, the set of public names includes all names found in the module’s namespace which do not begin with an underscore character ('_').__all__should contain the entire public API. It is intended to avoid accidentally exporting items that are not part of the API (such as library modules which were imported and used within the module).
PEP 8 использует аналогичную формулировку, хотя также дает понять, что импортированные имена не являются частью общедоступного API, когда __all__ отсутствует:
To better support introspection, modules should explicitly declare the names in their public API using the
__all__attribute. Setting__all__to an empty list indicates that the module has no public API.[...]
Imported names should always be considered an implementation detail. Other modules must not rely on indirect access to such imported names unless they are an explicitly documented part of the containing module's API, such as
os.pathor a package's__init__module that exposes functionality from submodules.
Кроме того, как указано в других ответах, __all__ используется для включения импорт подстановочных знаков для пакетов:
The import statement uses the following convention: if a package’s
__init__.pycode defines a list named__all__, it is taken to be the list of module names that should be imported whenfrom package import *is encountered.
__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 * будет импортировать только эти имена.
Обратите внимание, что в неявном случае python не будет импортировать имена, начинающиеся с _. Однако вы можете принудительно импортировать такие имена с помощью __all__.
Вы можете просмотреть документ Python здесь.
__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',)
См. Также Почему «импорт *» - это плохо?
Это определено в PEP8 здесь:
Global Variable Names
(Let's hope that these variables are meant for use inside one module only.) The conventions are about the same as those for functions.
Modules that are designed for use via
from M import *should use the__all__mechanism to prevent exporting globals, or use the older convention of prefixing such globals with an underscore (which you might want to do to indicate these globals are "module non-public").
PEP8 предоставляет соглашения о кодировании для кода Python, составляющего стандартную библиотеку в основном дистрибутиве Python. Чем больше вы следуете этому, тем ближе вы к первоначальному замыслу.
Объекты, начинающиеся с подчеркивания или не упомянутые в
__all__, если присутствует__all__, не являются полностью скрытыми; их можно увидеть и получить к ним доступ совершенно нормально, если вы знаете их имена. Только в случае «import *», который в любом случае не рекомендуется, различие имеет какой-либо вес.