Как я должен выполнять импорт в модуле Python без загрязнения его пространства имен?

Я разрабатываю пакет 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.
     

    Это удается для решения обеих проблем, загрязнение пространства имен модуля и простота использования для функций ... Но, похоже, вообще не питон.

Так какое решение является самой питоной? Есть ли еще одно хорошее решение, которое я пропустил из виду?

31
задан CharlesB 25 February 2013 в 15:27
поделиться

4 ответа

Импортировать модуль целиком: import foreignmodule. То, что вы считаете недостатком, на самом деле является преимуществом. А именно, добавление имени модуля облегчает поддержку вашего кода и делает его более самодокументированным.

Через шесть месяцев, когда вы посмотрите на строку кода, подобную foo = Bar(baz), вы можете спросить себя, откуда появился модуль Bar, но с foo = cleverlib.Bar это гораздо меньше загадки.

Конечно, чем меньше импорт, тем меньше проблем. Для небольших программ с небольшим количеством зависимостей это не имеет большого значения.

Когда вы начинаете задавать подобные вопросы, спросите себя, что облегчает понимание кода, а не то, что облегчает написание кода. Ты пишешь это один раз, но много читаешь.

9
ответ дан 27 November 2019 в 22:31
поделиться

Я бы пошел на компромисс и просто выбрал бы короткий псевдоним для внешнего модуля:

import foreignmodule as fm

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

1
ответ дан 27 November 2019 в 22:31
поделиться

Я знаю, что это старый вопрос. Возможно, это не «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

Однако, имейте в виду их общедоступные определения, конечно, будут совпадать.

0
ответ дан 27 November 2019 в 22:31
поделиться

Для этой ситуации я бы пошел с файлом 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 более структурированным? для получения дополнительной информации.

3
ответ дан 27 November 2019 в 22:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: