目的是实现某种插件框架,其中插件是相同基类(即A)的子类(即B)。基类通过标准导入进行加载,而子类通过知名包(即pkg)的路径通过imp.load_module()进行加载。

pkg/
    __init__.py
    mod1.py
        class A
    mod2.py
        class B(pkg.mod1.A)

这对于真正的子类(即,
# test_1.py
import pkg
from pkg import mod1
import imp
tup = imp.find_module('mod2', pkg.__path__)
mod2 = imp.load_module('mod2', tup[0], tup[1], tup[2])
print(issubclass(mod2.B, mod1.A)) # True

但是问题出在测试基类本身时
# test_2.py
import pkg
from pkg import mod1
import imp
tup = imp.find_module('mod1', pkg.__path__)
mod0 = imp.load_module('mod1', tup[0], tup[1], tup[2])
print(issubclass(mod0.A, mod1.A)) # False

但是mod0.A和mod1.A实际上是同一文件(pkg/mod1.py)中的同一类。

此问题同时出现在python 2.7和3.2中。

现在的问题有两个:a)它是issubclass()的预期功能还是bug,并且b)如何在不更改pkg内容的情况下摆脱它?

最佳答案

他们不是同一类。它们是用相同的代码创建的,但是由于您执行了两次该代码(一次在导入中,一次在load_module中),您将获得两个不同的类对象。 issubclass正在比较类对象的身份,它们是不同的。

编辑:由于您不能依赖issubclass,因此一种可能的选择是在基类上创建一个唯一的属性,该属性将由派生类继承。该属性也将存在于类的副本中。然后,您可以测试该属性。

class A:
    isA = True

class B(A):
    pass

class C:
    pass

def isA(aclass):
    try:
        return aclass.isA
    except AttributeError:
        return False

print isA(A)
True
print isA(B)
True
print isA(C)
False

09-12 09:07