首先:不要这样做.
可能有更好的方法来解决您的具体问题。如果你必须为一个类定义大量相关的方法,并且想要使用模块来组织这些方法,那么给每个模块一个基类,在这些类上定义方法,然后将模块中的类合并为一个:使用子类化。见下文。
为什么不允许导入类中的所有内容
因为类语句是 Python 的作用域命名空间,在编译时,需要知道哪些名称被引用为全局名称,并将它们与本地名称区分开来。这在函数中尤其重要,其中通过了解使用的名称来高度优化本地命名空间在编译时。对于类语句,“本地”名称成为类属性。当涉及到动态本地名称时,类语句比函数更灵活,但将任意动态名称列表导入到类定义中从未被视为值得支持的用例。
我该如何解决这个问题
您可以内省模块并获取 Python 将导入的所有相同名称,并使用动态在类上设置这些名称setattr()
或者通过分配给locals()
字典(类语句是后者实际工作的唯一地方)。这import声明文件 https://docs.python.org/3/reference/simple_stmts.html#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)
或者,这肯定更“hack-y”,并且取决于内部 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
where bar.py
将定义一个Base
class:
class Base:
def print_bar(self):
print("bar")
也是如此spam
等等。您可以根据需要向这些混合基类添加和删除方法,并且import
组合基类的语句不会改变。