这是我正在努力的事情的最小再现。这是使用Python 3.6.5:
sample.py:
import importlib.util
import inspect
from test import Test
t = Test()
spec = importlib.util.spec_from_file_location('test', './test.py')
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
loaded_test = None
for name, obj in inspect.getmembers(module):
if inspect.isclass(obj):
loaded_test = obj
print(type(t))
print(loaded_test)
print(isinstance(t, loaded_test))
print(issubclass(t.__class__, loaded_test))
test.py(在同一目录中):
class Test(object):
pass
运行此代码将为您提供以下输出:
<class 'test.Test'>
<class 'test.Test'>
False
False
那么为什么我们使用importlib加载的对象被标识为&#39; test.Test&#39;,而不是&#39; test.Test&#39;的实例或子类。我使用import创建的类?有没有办法以编程方式检查它们是否属于同一个类,还是因为实例化的上下文不同而不可能?
答案 0 :(得分:2)
为什么我们使用
importlib
加载的对象(标识为test.Test
)不是我使用import创建的test.Test
类的实例或子类?
一个班级是&#34;只是&#34;元类的一个实例。导入系统通常会阻止类对象多次实例化:类通常在模块范围内定义,如果已导入模块,则现有模块仅用于后续导入语句。因此,对同一个类的不同引用最终都指向生活在同一内存位置的相同类对象。
通过使用exec_module
,你阻止了这个&#34;缓存命中&#34;在sys.modules 中,强制再次执行类声明,并在内存中创建一个新的类对象。
issubclass
没有像对源类代码进行深入检查那样聪明,它或多或少只是寻找身份(CPython的实现here,快速跟踪完全匹配以及支持ABCs)
有没有办法以编程方式检查它们是否属于同一个类,还是因为实例化的上下文不同而不可能?
他们不是同一个班级。虽然源代码相同,但它们存在于不同的内存位置。你不需要exec_module
的并发症来看这个,顺便说一下,有更简单的方法可以强制重新使用&#34;相同的&#34;类:
>>> import test
>>> t = test.Test()
>>> isinstance(t, test.Test)
True
>>> del sys.modules['test']
>>> import test
>>> isinstance(t, test.Test)
False
或者,在函数块中定义类并从函数调用中返回它。或者,使用三参数版本的type(name, bases, dict)
从相同的源代码创建类。 isinstance
检查(CPython实现here)很简单,不会检测到这些误导。