Я разрабатываю пакет Python для решения некоторых научных данных. Существует несколько часто используемых классов и функций из других модулей и пакетов, включая Numpy, что мне нужно практически во всех функциях, определенных в любом модуле пакета.
Что будет питоновым способом разобраться с ними? Я считал несколько вариантов, но у каждого есть свои недостатки.
Импортируйте классы на уровне модуля с из
от ImportModule Import Class1, Class2, Function1, Function2
, затем импортируемые функции и классы легко доступны из любой функции. С другой стороны, они загрязняют модуль пространства имен Dir (Package.Module)
и )
и (Package.Module)
загромождаются с импортированными функциями
Импортируйте классы на уровне функции С из
от EnternalModule Import Class1, Class2, Function1, Function2
Функции и классы легко доступны и не загрязняют модуль, а импорт от до десятка модулей в каждой функции выглядят как много дубликатов.
Импортируйте модули на уровне модуля с Импорт иностранцы
Не слишком много загрязнений компенсируется необходимостью добавления имени модуля для каждой функции или класса.
Используйте какой-либо искусственный обходной путь, например, использование функционального тела для всех этих манипуляций и возврата только объектов, которые будут экспортированы ... Как этот
Def _Export ():
Из иностранных компаний Import Class1, Class2, Function1, Function2
def myfunc (x):
Функция возврата1 (x, function2 (x)))
вернуть myfunc.
myfunc = _Export ()
del _export.
Это удается для решения обеих проблем, загрязнение пространства имен модуля и простота использования для функций ... Но, похоже, вообще не питон.
Так какое решение является самой питоной? Есть ли еще одно хорошее решение, которое я пропустил из виду?
Импортировать модуль целиком: import foreignmodule
. То, что вы считаете недостатком, на самом деле является преимуществом. А именно, добавление имени модуля облегчает поддержку вашего кода и делает его более самодокументированным.
Через шесть месяцев, когда вы посмотрите на строку кода, подобную foo = Bar(baz)
, вы можете спросить себя, откуда появился модуль Bar
, но с foo = cleverlib.Bar
это гораздо меньше загадки.
Конечно, чем меньше импорт, тем меньше проблем. Для небольших программ с небольшим количеством зависимостей это не имеет большого значения.
Когда вы начинаете задавать подобные вопросы, спросите себя, что облегчает понимание кода, а не то, что облегчает написание кода. Ты пишешь это один раз, но много читаешь.
Я бы пошел на компромисс и просто выбрал бы короткий псевдоним для внешнего модуля:
import foreignmodule as fm
Это полностью спасает вас от загрязнения (возможно, более серьезная проблема) и, по крайней мере, уменьшает предваряющее бремя.
Я знаю, что это старый вопрос. Возможно, это не «Pythonic», но самый чистый способ, который я обнаружил для экспорта только определенных определений модулей, это, как вы уже нашли, глобально обернуть модуль в функцию. Но вместо того, чтобы возвращать их, чтобы экспортировать имена, вы можете просто глобализировать их (глобальный, таким образом, по сути становится своего рода ключевым словом «экспорта»):
def module(): global MyPublicClass,ExportedModule import somemodule as ExportedModule import anothermodule as PrivateModule class MyPublicClass: def __init__(self): pass class MyPrivateClass: def __init__(self): pass module() del module
Я знаю, что это не сильно отличается от вашего первоначального заключения, но, честно говоря, мне кажется, что это самый чистый вариант. Другое преимущество состоит в том, что вы можете сгруппировать любое количество модулей, написанных таким образом, в один файл, и их частные термины не будут пересекаться:
def module(): global A i,j,k = 1,2,3 class A: pass module() del module def module(): global B i,j,k = 7,8,9 # doesn't overwrite previous declarations class B: pass module() del module
Однако, имейте в виду их общедоступные определения, конечно, будут совпадать.
Для этой ситуации я бы пошел с файлом all_imports.py
, в котором были все
from foreignmodule import .....
from another module import .....
, а затем в ваших рабочих модулях
import all_imports as fgn # or whatever you want to prepend
...
something = fgn.Class1()
Еще одна вещь, о которой нужно знать
__all__ = ['func1', 'func2', 'this', 'that']
Теперь любые функции / классы / переменные / и т. Д., Которые есть в вашем модуле, но не в __all__
ваших модулей, не будут отображаться в help()
и будут выиграны ' from mymodule import *
См. Как сделать импорт Python более структурированным? для получения дополнительной информации.