Прежде всего: Не делайте этого .
Возможно, есть более эффективные способы решения вашей конкретной проблемы. Если вам нужно определить большое количество связанных методов для класса, и вы хотите использовать модули для организации этих методов, то дайте каждому модулю базовый класс, определите методы для этих классов, а затем объедините классы из модулей в один. используя подклассы. См. Ниже.
Почему нельзя импортировать все в классе
Поскольку оператор класса представляет собой пространство имен с областью действия, где Python, во время компиляции Необходимо знать, на какие имена ссылаются как глобальные, и отличать их от локальных имен. Это особенно важно в функциях, где локальное пространство имен высоко оптимизировано, зная, какие имена используются во время компиляции . Для оператора класса «локальные» имена становятся атрибутами класса. Оператор класса является более гибким, когда речь идет о динамических локальных именах, чем функции, но импорт произвольного динамического списка имен в определение класса никогда не рассматривался как вариант поддержки, достойный поддержки.
как я могу обойти это
Вы можете проанализировать модуль и получить все те же имена, которые импортирует Python, и установить их в классе динамически, используя setattr()
или путем присвоения словарю locals()
(оператор класса является единственным местом, где последний действительно работает). В документации import
указано, что импортируется:
- Если модуль определяет
__all__
, то он используется в качестве списка имен для импорта - В противном случае импортируются все публичные имена (все глобальные имена с именами, которые не начинаются с
_
).
Таким образом, следующее будет иметь тот же эффект, что и использование from bar import *
внутри классаоператор для Foo
:
import bar
def _import_all(module, class):
namespace = vars(module)
public = (name for name in namespace if name[:1] != "_")
for name in getattr(module, "__all__", public):
setattr(class, name, namespace[name])
class Foo:
pass
_import_all(bar, Foo)
или, и это определенно более «хак-у» и в зависимости от внутренних деталей реализации Python:
import bar
class Foo
locals().update(
(n, getattr(bar, n))
for n in getattr(
bar, "__all__",
(n for n in dir(bar) if n[:1] != "_")
)
)
есть лилучший способ разделить несколько методов на разные файлы?
Да, используйте классы. Поместите все эти методы в отдельные модули, каждый в классе , затем просто импортируйте эти классы из каждого модуля и используйте его в качестве базового класса:
import bar, spam
class Foo(bar.Base, spam.Base):
pass
, где bar.py
будет определятькласс Base
:
class Base:
def print_bar(self):
print("bar")
и т. п. spam
и т. д. При необходимости вы можете добавлять и удалять методы для этих базовых классов смешивания, а операторы import
для объединения базовых классовне меняется.