Python: Почему «из <module> import *» запрещается?

Если у вас

from <module> import * 

в середине вашей программы (или модуля) вы получите предупреждение:

 /tmp/foo:100: SyntaxWarning: import * only allowed at module level 

Я понимаю, почему import * не рекомендуется вообще (невидимость пространства имен), но есть много ситуаций, когда это будет удобно, особенно если код не используется никому.

Итак, может ли кто-нибудь точно объяснить, почему from <module> import * должно быть запрещено во всех возможных случаях?

  • Объявить функцию в конце файла в Python
  • Как изменить версию python в anaconda spyder
  • Импорт нестандартного модуля python в Jython
  • Python, подсчеты для сравнения и составление списка
  • SQLAlchemy или psycopg2?
  • Как вы создаете график ошибок в matplotlib, используя linestyle = None в rcParams?
  • python-pandas и базы данных, такие как mysql
  • Какую (чистую) библиотеку Python использовать для шифрования AES 256?
  • 6 Solutions collect form web for “Python: Почему «из <module> import *» запрещается?”

    Я полагаю, что «в середине вашей программы» вы говорите об импорте внутри определения функции:

     def f(): from module import * # not allowed 

    Это не допускается, потому что это слишком сильно оптимизирует тело функции. Реализация Python хочет знать все имена функционально-локальных переменных, когда он байт-компилирует функцию, чтобы он мог оптимизировать ссылки на переменные в операциях в стеке операнда виртуальной машины (CPython) или, по крайней мере, в локальном переменном слоте а не поисками в внешних пространствах имен. Если вы могли бы сбросить все содержимое модуля в локальное пространство имен функции, тогда компилятор должен был предположить, что любое имя в функции может ссылаться на модуль глобальный, поскольку список имен, внесенных from module import * является только известный во время работы.

    Помещение from module import * между объявлениями верхнего уровня плохое, но разрешено:

     def f(): ... from module import * def g(): ... 

    EDIT Апрель 2013 года. Изучая что-то еще, я обнаружил, что это ограничение было введено в Python 2.1 как следствие функции «Вложенные области» ( PEP 227 ). Цитата из ссылки:

    Один из побочных эффектов этого изменения заключается в том, что from module import * и exec были сделаны незаконными внутри области функций при определенных условиях. В справочном руководстве Python все сказано, что from module import * является только законным на верхнем уровне модуля, но интерпретатор CPython никогда не применял это раньше. В рамках реализации вложенных областей компилятор, который превращает исходный код Python в байт-коды, должен генерировать другой код для доступа к переменным в области содержимого. from module import * и exec позволяют компилятору понять это, потому что они добавляют имена в локальное пространство имен, которые непознаваемы во время компиляции. Поэтому, если функция содержит определения функций или lambda выражения со свободными переменными, компилятор отметит это, подняв исключение SyntaxError .

    Это разъясняет поведение Python 3.x vs 2.x, обсуждаемое в комментариях. Это всегда противоречит спецификации языка, но CPython с 2.1 по 2.7 только выдает ошибку from module import * за from module import * внутри функции, если это может повлиять на способность компилятора узнать, привязывается ли переменная локально или в области содержимого. В 3.x он был доведен до безусловной ошибки.

    СЫН РЕДАКТИРОВАНИЯ: … и, по-видимому, Флэшк указал на это много лет назад в другом ответе, цитируя тот же абзац «Что нового в Python 2.1». Теперь я пойду вверх.

    На любом лексическом уровне from amodule import * – это «казалось бы хорошей идеей в то время» дизайнерское решение, которое оказалось реальной катастрофой в реальной жизни, за исключением удобного исследования в интерактивном интерпретаторе (даже тогда, m не слишком жарко на нем – import module as m заставляет только два дополнительных символа использовать вместо них квалифицированные имена [[только префикс m. ]], а квалифицированные имена всегда более четкие и гибкие, чем барные имена, не говоря уже о большой полезности в поисковых интерактивных ситуациях, когда m доступно для help(m) , reload(m) и тому подобное!).

    Эта разрушенная конструкция делает ее очень трудной, поскольку бедный человек, читающий код (часто в обреченной попытке помочь отлаживать его), понимает, откуда происходят таинственно возникающие имена – невозможно, если конструкция используется более одного раза на лексический уровень; но даже когда он используется только один раз, он заставляет кропотливо перечитывать весь модуль каждый раз, прежде чем можно убедить себя в том, что, да, это изнасилованное барное имя должно появиться из модуля.

    Плюс, авторы модулей обычно не идут на крайние проблемы, необходимые для «поддержки» ужасной конструкции, о которой идет речь. Если где-то в вашем коде у вас есть, скажем, использование sys.argv (и, конечно, import sys на самом верху вашего модуля), откуда вы знаете, что sys – это модуль, который должен быть … или некоторые совершенно другой (или немодульный), исходящий из ... import * ?! Умножьте, что по всем квалифицированным именам вы используете, а несчастье – единственный конечный результат – это и загадочные ошибки, требующие долгой, кропотливой отладки (обычно с неохотой помощью кого-то, кто «получает» Python …! – ).

    В рамках функции способ добавления и переопределения произвольных локальных имен будет еще хуже. В качестве элементарной, но решающей оптимизации компилятор Python просматривает тело функции для любого присваивания или других операторов привязки для каждого имени и считает «локальным» те имена, которые он видит таким образом (остальные должны быть глобальными или встроенными). С import * (точно так же, как с exec somestring без явных dicts для использования в качестве пространств имен), вдруг становится полной тайной, имена которой локальны, имена которых глобальны – поэтому бедному компилятору придется прибегать к самой медленной возможной стратегии для каждого поиска имени, используя dict для локальных переменных (вместо компактного «вектора», который он обычно использует) и выполняет до трех исканий для каждого упоминаемого барана, снова и снова.

    Перейдите в любую интерактивную подсказку Python. Введите import this . Что ты видишь? Дзен Питона. Какая последняя и, вероятно, самая большая мудрость в этом тексте …?

    Пространства имен – одна хорошая идея – давайте сделаем больше!

    Заставляя использовать барные имена, где квалифицированные имена настолько значительно предпочтительнее, вы по существу делаете очень противоположную эту мудрую рекомендацию: вместо того, чтобы восхищаться величием и хонингованием пространств имен и делать больше из них, вы разбиваете два совершенно хорошие и готовые к использованию пространства имен (импортируемого модуля, а также лексического объема, в который вы импортируете его), чтобы создать единый, нечестивый, багги, медленный, жесткий, непригодный беспорядок.

    Если бы я мог вернуться и изменить одно раннее дизайнерское решение на Python (это трудный выбор, потому что использование def и особенно lambda для того, что Javascript вызывает гораздо более читабельную function – это вторая секунда ;-), я бы задним числом уничтожил import * идеи из ума Гвидо. Никакое количество предполагаемого удобства для исследования в интерактивном приглашении не может сбалансировать количество зла, которое оно совершило …! -)

    Заметки о выпуске для Python 2.1, похоже, объясняют, почему это ограничение существует:

    Один из побочных эффектов этого изменения заключается в том, что из-за ошибок в модуле import * и exec были сделаны незаконными внутри области функций при определенных условиях. В справочном руководстве Python все сказано, что из модуля import * является только законным на верхнем уровне модуля, но интерпретатор CPython никогда не применял это раньше. В рамках реализации вложенных областей компилятор, который превращает исходный код Python в байт-коды, должен генерировать другой код для доступа к переменным в области содержимого. из модуля import * и exec не позволяют компилятору понять это, потому что они добавляют имена в локальное пространство имен, которые непознаваемы во время компиляции. Поэтому, если функция содержит определения функций или лямбда-выражения со свободными переменными, компилятор отметит это, подняв исключение SyntaxError.

    Это не запрещено, потому что …

    … это удобно для быстрых сценариев и изучения оболочки.

    … но вы не должны держать его в каком-либо серьезном коде

    1. это может привести к импорту имен, о которых вы не знаете, и удалении локальных имен
    2. вы не можете знать, что используется в вашем коде, трудно понять зависимости скрипта
    3. завершение кода не будет работать корректно
    4. Удобные проверки IDE, такие как «этот var не был объявлен», больше не могут работать
    5. упростить создание кругового импорта

    Это не запрещено. Он отлично работает, но вы получаете предупреждение, потому что это, как правило, плохая идея (по другим причинам). Вы можете, если хотите, подавить предупреждение; модуль предупреждений – это то, что вы хотите для этого.

    другие дали подробные ответы, я дам краткий обзорный ответ моего понимания. При использовании от вас вы делаете это так, чтобы вы могли напрямую вызывать любую функцию в том модуле, который вы импортировали, не выполняя modulename.functioname (вы можете просто позвонить «functionname»), это создает проблемы, если у вас есть 2 функции с одним и тем же именем в разных модулях, а также может создавать путаницу при работе с множеством функций, так как вы не знаете, к какому объекту / модулю он принадлежит (с точки зрения кто-то просматривает уже написанный код, который не знаком с ним)

    Python - лучший язык программирования в мире.