我有一个python源文件,其中定义了一个类,另一个模块中的类导入了该文件。基本上,这个结构:
from parent import SuperClass
from other import ClassA
class ClassB(SuperClass):
def __init__(self): pass
我想要做的是在这个模块中查找那里定义的所有类,并且只查找ClassB(并忽略ClassA)。 ClassA和ClassB都扩展了SuperClass。
原因是我有一个在运行时加载的插件目录,我通过对每个.py文件进行内省并加载扩展SuperClass的类来获得插件类的完整列表。在这种特殊情况下,ClassB使用插件ClassA为它做一些工作,因此依赖于它(同时,ClassA不依赖于ClassB)。问题是,当我从目录加载插件时,我得到2个ClassA实例,因为它从ClassA的文件中获取一个,而从ClassB的文件中获取一个。
对于包,有方法:
__all__ = ['module_a', 'module-b']
显式列出您可以导入的模块,但它存在于__init__.py
文件中,每个插件都是.py文件,而不是它自己的目录。
那么问题是:我可以限制对.py文件中的类的访问,还是我必须使用自己的init文件使每个类都成为一个目录?或者,是否有其他一些聪明的方法可以区分这两个类?
答案 0 :(得分:1)
你的意思是“对于包裹有方法......”。实际上,这适用于每个模块(__init__.py
一个模块,只有特殊的语义)。在插件模块中使用__all__
即可。
但请记住:__all__
仅限制您使用from xxxx import *
导入的内容;您仍然可以访问模块的其余部分,并且无法使用标准的Python导入机制来避免这种情况。
如果您正在使用某种有效的内省技术(例如,在模块中探索命名空间然后从中导入类),您可以检查该类是否来自与模块本身相同的文件。
您也可以实现自己的导入机制(例如,使用importlib
),但这可能有点过分......
编辑:对于“检查班级是否来自同一模块”:
假设我有两个模块,mod1.py
:
class A(object):
pass
和mod2.py
:
from mod1 import A
class B(object):
pass
现在,如果我这样做:
from mod2 import *
我已导入A
和B
。但...
>>> A
<class 'mod1.A'>
>>> B
<class 'mod2.B'>
如你所见,这些课程带有关于它们起源的信息。实际上你可以马上检查一下:
>>> A.__module__
'mod1'
>>> B.__module__
'mod2'
使用这些信息可以轻松区分它们。