为什么 isinstance() 在这种情况下返回 False?



我想写一个允许记忆构造函数的装饰器。当我构造一个类时,我希望尽可能从缓存中返回对象。

以下代码已从此处改编。

from functools import wraps

def cachedClass(klass):
cache = {}
@wraps(klass, updated=())
class wrapper:
def __new__(cls, *args, **kwargs):
key = (cls,) + args + tuple(kwargs.items())
try:
inst = cache.get(key, None)
except TypeError:
# Can't cache this set of arguments
inst = key = None
if inst is None:
inst = klass.__new__(klass, *args, **kwargs)
inst.__init__(*args, **kwargs)
if key is not None:
cache[key] = inst
return inst
return wrapper

小型测试套件具有以下价值:

>>> @cachedClass
... class Foo:
...     pass
>>> f1 = Foo()
>>> f2 = Foo()
>>> f1 is f2
True
>>> Foo
<class 'cache.Foo'>
>>> type(f1)
<class 'cache.Foo'>
>>> isinstance(f1, Foo)
False

我预计最后一个表达式会返回True.我错过了什么?

@cachedClass
class Foo:
pass

在语义上等效于

class Foo:
pass
Foo = cachedClass(Foo)

Foo名称被分配返回值cachedClass,即wrapper类。

wrapper又由复制Foo__name__属性以及其他一些 dunder 属性的functool.wraps装饰,因此wrapper看起来像Foo

如果删除@wraps行并打印

print(type(f1), Foo, type(f1) is Foo, sep=', ')

您将看到f1是原始Foo类的实例,但Foo名称现在引用wrapper类,它们是不同的对象:

<class '__main__.Foo'>, <class '__main__.cachedClass.<locals>.wrapper'>, False

最新更新