给出以下文件:
a.py
-----
class CommonClass(object):
def do_thing(self):
pass
b.py
-----
from a import CommonClass
class SubClassA(CommonClass):
def do_thing(self):
print("I am A")
class SubClassB(CommonClass):
def do_thing(self):
print("I am B")
c.py
-----
from a import CommonClass
from b import SubClassA
if __name__ == "__main__":
for member in CommonClass.__subclasses__():
member().do_thing()
我希望仅导入SubClassA
,并且在遍历CommonClass
的子类时可见,但是似乎也导入SubClassB
。
我正在运行Python 3.8.5,这是python3 c.py
的输出:
$ python3 c.py
I am A
I am B
如何仅导入所需的类?
答案 0 :(得分:3)
您没有仅将SubClassA
导入到c.py
。可以通过做这件事来测试
x = SubClassB()
或
x = b.SubClassB()
两者都会导致NameError
。
问题是,当您import
使用文件时,实际上正在运行它,即使使用from x import y
!
通过在print("I'm from b.py")
的末尾添加b.py
然后运行c.py
可以很容易地看到这一点。
这使得SubClassA
和SubClassB
都是您导入的CommonClass
的子类。因此,虽然您无权访问SubClassB
名称,但它仍然是CommonClass
的子类,您可以从那里访问它。
通常,您不必导入模块即可使用其对象。导入将扩展您的名称空间以包括该模块,因此您可以直接创建对象。即使您以其他方式获得了该模块的对象,即使不导入也可以使用它(例如,导入第三个模块,该模块从第二个模块返回对象)。
无论如何,您现在甚至都没有真正使用导入的SubClassA
。如果要“允许”某些类仅从外部来源考虑,则可以创建允许的一组类:
from a import CommonClass
from b import SubClassA
allowed_classes = {SubClassA}
if __name__ == "__main__":
for member in CommonClass.__subclasses__():
if member in allowed_classes:
member().do_thing()
仅打印I am A
答案 1 :(得分:0)
from a import CommonClass
from b import SubClassA
if __name__ == "__main__":
h = CommonClass.__subclasses__()[0]()
h.do_thing()
您可以这样做。