Class 动态加载中的标识 类 v.s。 类 通过导入加载
Class Identification in dynamically loaded classes v.s. classes loaded by import
这是我正在处理的内容的最小复制。这是使用 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加载的对象,标识为'test.Test',而不是我创建的'test.Test' class的实例或子class使用导入?有没有办法以编程方式检查它们是否相同 class,或者是否不可能因为它们实例化的上下文不同?
Why is the object that we load using importlib
, which is identified as test.Test
, not an instance or subclass of the test.Test
class I created using import?
A class 是 "just" 元 class 的实例。导入系统通常会阻止 class 对象被多次实例化:classes 通常是在模块范围内定义的,如果模块已经被导入,则现有模块只会被重复用于后续的导入语句.因此,对同一 class 的不同引用最终都指向位于同一内存位置的相同 class 对象。
通过使用 exec_module
你在 sys.modules 中阻止了这个 "cache hit",强制再次执行 class 声明,以及要在内存中创建的新 class 对象。
issubclass
并没有像深入检查 class 源代码那样聪明,它或多或少只是在寻找身份(CPython 的实现 here, with a fast-track for exact match and some complications for supporting ABCs)
Is there a way to programmatically check if they're the same class, or is it impossible because the context of their instantiation is different?
它们不一样class。尽管源代码相同,但它们存在于不同的内存位置。你不需要 exec_module
的复杂性来看到这个,顺便说一下,有更简单的方法来强制重新创建 "same" class:
>>> import test
>>> t = test.Test()
>>> isinstance(t, test.Test)
True
>>> del sys.modules['test']
>>> import test
>>> isinstance(t, test.Test)
False
或者,在函数块中定义 class 并从函数调用中定义 return。或者,使用 type(name, bases, dict)
. The isinstance
check (CPython implementation here) 的三参数版本从相同的源代码创建 classes 很简单,并且不会检测到这些误导。
这是我正在处理的内容的最小复制。这是使用 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加载的对象,标识为'test.Test',而不是我创建的'test.Test' class的实例或子class使用导入?有没有办法以编程方式检查它们是否相同 class,或者是否不可能因为它们实例化的上下文不同?
Why is the object that we load using
importlib
, which is identified astest.Test
, not an instance or subclass of thetest.Test
class I created using import?
A class 是 "just" 元 class 的实例。导入系统通常会阻止 class 对象被多次实例化:classes 通常是在模块范围内定义的,如果模块已经被导入,则现有模块只会被重复用于后续的导入语句.因此,对同一 class 的不同引用最终都指向位于同一内存位置的相同 class 对象。
通过使用 exec_module
你在 sys.modules 中阻止了这个 "cache hit",强制再次执行 class 声明,以及要在内存中创建的新 class 对象。
issubclass
并没有像深入检查 class 源代码那样聪明,它或多或少只是在寻找身份(CPython 的实现 here, with a fast-track for exact match and some complications for supporting ABCs)
Is there a way to programmatically check if they're the same class, or is it impossible because the context of their instantiation is different?
它们不一样class。尽管源代码相同,但它们存在于不同的内存位置。你不需要 exec_module
的复杂性来看到这个,顺便说一下,有更简单的方法来强制重新创建 "same" class:
>>> import test
>>> t = test.Test()
>>> isinstance(t, test.Test)
True
>>> del sys.modules['test']
>>> import test
>>> isinstance(t, test.Test)
False
或者,在函数块中定义 class 并从函数调用中定义 return。或者,使用 type(name, bases, dict)
. The isinstance
check (CPython implementation here) 的三参数版本从相同的源代码创建 classes 很简单,并且不会检测到这些误导。