Автостопом по Python | страница 51
Вы можете симулировать более привычное поведение, используя специальный синтаксис в выражении import: from modu import *. Однако это, как правило, считается признаком плохого тона: наличие конструкции import * усложняет чтение кода, делает зависимости более связанными и может затереть (перезаписать) существующие определенные объекты новыми описаниями из импортированного модуля.
Нотация from modu import func — это способ импортировать только необходимые вам атрибуты в глобальное пространство имен. Она гораздо безопаснее нотации from modu import *, поскольку явно показывает, что именно импортируется в глобальное пространство имен. Единственное ее преимущество перед более простой нотацией import modu в том, что она сэкономит вам немного времени.
В табл. 4.1 сравниваются разные способы импортирования определений из других модулей.
Очень плохой код (непонятный для читателя) | Код получше (здесь понятно, какие имена находятся в глобальном пространстве имен) | Лучший код (сразу понятно, откуда появился тот или иной атрибут) |
---|---|---|
from modu import * | from modu import sqrt | import modu |
x = sqrt(4) | x = sqrt(4) | x = modu.sqrt(4) |
from modu import sqrt | from modu import sqrt | from modu import sqrt |
Как упоминается в разделе «Стиль кода» в начале этой главы, читаемость — одна из основных особенностей Python. Читаемый код не содержит бесполезного текста. Но не следует максимально его сокращать в угоду краткости. Явно указывая, откуда появился тот или иной класс или функция, как в случае идиомы modu.func(), вы повышаете читаемость кода и степень его понимания.
Несмотря на то что вы можете структурировать проект так, как вам нравится, следует избегать некоторых ошибок.
• Большое количество запутанных циклических зависимостей. Если для ваших классов Table и Chair из файла furn.py нужно импортировать класс Carpenter из файла workers.py (чтобы ответить на вопрос table.is_done_by() («произведены кем?»)) и если для класса Carpenter нужно импортировать классы Table и Chair (чтобы ответить на вопрос carpenter.what_do() («что производит?»)), у вас имеется циклическая зависимость: файл furn.py зависит от файла workers.py, который зависит от файла furn.py. В таком случае вам нужно использовать выражение import внутри методов, дабы избежать исключения ImportError.
• Скрытое связывание. После каждого изменения в реализации класса Table вдруг перестают работать 20 несвязанных с ним тестов, поскольку это нарушает реализацию класса Carpenter. Это требует проведения аккуратных изменений для того, чтобы к ним адаптироваться, и означает, что в своем коде класса Carpenter вы делаете слишком много предположений о классе Table.