"from module import class" 从同一模块导入其他 类

"from module import class" importing other classes from same module

给定以下文件:

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

如何只导入我想要的类?

导入 SubClassAc.py。这可以通过做

来测试
x = SubClassB()

x = b.SubClassB()

两者都会导致 NameError

问题是,当您 import 一个文件时,它实际上是 运行、,即使在使用 from x import y 时也是如此!

b.py的末尾加一个print("I'm from b.py")然后运行c.py.

就很容易看出来了

这使得 SubClassASubClassB 都成为您导入的 CommonClass 的子 类。因此,虽然您无法访问 SubClassB name,但它仍然是 CommonClass 的子类,您可以从那里访问它。


一般来说,您不必导入模块就可以使用它的对象。导入会扩展您的命名空间以包含该模块,以便您可以直接创建对象。如果您以其他方式获取它们(例如导入第三个模块,returns 对象来自第二个模块),即使不导入它,您仍然可以使用该模块的对象。


不管怎样,你现在连导入的SubClassA都没有真正使用过。如果你想“允许”某些 类 只被认为来自外部来源,你可以创建一个 allowed 集 类:

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

from a import CommonClass
from b import SubClassA

if __name__ == "__main__":

    h = CommonClass.__subclasses__()[0]()
    h.do_thing()

你可以做到这一点。