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

Why does isinstance() return False in this case?

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

以下代码改编自here

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

我预计最后一个表达式会 return True。我错过了什么?

@cachedClass
class Foo:
    pass

在语义上等同于

class Foo:
    pass

Foo = cachedClass(Foo)

Foo 名称被分配了 cachedClass 的 return 值,这是 wrapper class.

wrapper 又被 functool.wraps 修饰,它复制了 Foo__name__ 属性以及一些其他的 dunder 属性,所以 wrapper class 看起来Foo.

如果删除 @wraps 行并打印

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

你会看到 f1 是原始 Foo class 的实例,但是 Foo name 现在指的是 wrapper class,它们是不同的对象:

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