我想写一个装饰器,它允许构造函数的memoiziation。当我构造一个类时,我想尽可能从缓存返回对象。
以下代码改编自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
我希望最后一个表达式返回True
。我错过了什么?
答案 0 :(得分:3)
@cachedClass
class Foo:
pass
在语义上等同于
class Foo:
pass
Foo = cachedClass(Foo)
Foo
名称的返回值为cachedClass
,即{。}}
wrapper
上课。
wrapper
依次由functool.wraps
修饰,复制Foo
的{{1}}属性以及其他一些dunder属性,因此__name__
类看起来像<{1}} 。
如果您删除wrapper
行并打印
Foo
您会看到@wraps
是原始print(type(f1), Foo, type(f1) is Foo, sep=', ')
类的实例,但f1
名称现在引用{{1} } class,它们是不同的对象:
Foo