Доступен ли порядок определения в пространстве имен модулей?

Документально подтверждено, что порядок определения в классах сохраняется (см. также PEP 520):

Если у метакласса нет атрибута __prepare__, то пространство имен класса инициализируется как пустое упорядоченное отображение.

Сохраняется ли порядок определения в объектах модуля?

# foo_bar.py

def foo():
    pass

def bar():
    pass

Я экспериментировал с модулем выше (также меняя порядок), и он показался надежным:

>>> import foo_bar
>>> for name in foo_bar.__dict__:
...     if not name.startswith('_'):
...         print(name)
... 
foo
bar

Предположительно, пространство имен модулей также использует компактный словарь внизу, или, возможно, из того факта, что type(foo_bar) является <class 'module'>, следует, что он также должен соблюдать порядок определения, как и любой другой класс. Однако я не уверен, является ли это функцией, гарантированной Python, или просто деталью реализации CPython. Должны ли имена в модулях соблюдать порядок определений?


person wim    schedule 15.03.2017    source источник
comment
Насколько я знаю, это деталь реализации. Это может быть сделано явной гарантией позже или просто неявной гарантией из комбинации того, как указывается определение имени на уровне модуля и как указывается порядок словаря, когда порядок словаря фактически является частью спецификации.   -  person user2357112 supports Monica    schedule 16.03.2017
comment
Обратите внимание, что foo_bar не является классом. Вы, кажется, запутались в том, как type(foo_bar) имеет class в выводе. class в выводе просто означает, что type(foo_bar) — это класс; это не значит, что foo_bar сам по себе один.   -  person user2357112 supports Monica    schedule 16.03.2017
comment
Нет, мое предложение таково: Класс -> instance=Class() -> атрибуты экземпляра учитывают порядок, потому что пространство имен использует компактный словарь. ModuleType -> module=ModuleType() -> атрибуты модуля учитывают порядок (?), потому что пространство имен использует компактный словарь (?).   -  person wim    schedule 16.03.2017
comment
т. е. модуль — это просто экземпляр класса ModuleType.   -  person wim    schedule 16.03.2017
comment
Гарантии упорядочения еще не были распространены на все экземпляры всех классов, экземпляры которых имеют __dict__. Это все еще деталь реализации.   -  person user2357112 supports Monica    schedule 16.03.2017


Ответы (1)


Встроенные классы, такие как класс module, не проходят через обычный механизм, который делают определяемые пользователем классы*, и поэтому не используют metaclass.__prepare__. PEP 520 не распространяется на них, поэтому предоставляемые им гарантии не могут быть применены здесь.

Порядок пространства имен модулей в настоящее время сохраняется из-за порядка вставки словаря, поэтому, как и сам словарь, он считается деталью реализации.


* Определенные пользователем классы сначала проходят через build_class (функция, которую байт-код LOAD_BUILD_CLASS загружает, когда вы dis выполняете оператор класса) в bltinmodule.c. Это единственное место, где вызывается __prepare__ ( который возвращает PyDict_New из type_prepare, если пользовательская метаданная с __prepare__ не определено).

person Dimitris Fasarakis Hilliard    schedule 17.03.2017
comment
Какой тип серверной части хранилища использует пространство имен модулей и где оно создается? Я где-то слышал, что это особый тип словаря, оптимизированный для строковых ключей, но когда я проверил его в REPL, он показался мне обычным словарем, и я без проблем смог установить элемент с нестроковыми ключами. - person wim; 17.03.2017
comment
Я почти уверен, что он создан в недрах механизма импорта, но мне придется разобраться с этим и отомстить вам, @wim. Специальный тип dict, о котором вы говорите, может быть общий ключ, который существует для экземпляров, но я действительно не знаю, используется ли он также для модулей. - person Dimitris Fasarakis Hilliard; 17.03.2017