我放弃了一个班级的记忆,作为一个我不想探索的包虫,这里有一个例子。我问的问题是"如何从一个记忆的类中扩展或继承"但我很可能犯了一个错误。下面的memoize类是brandizzi在How can I memoize a class instantiation in Python?中的一个简化版本,谷歌搜索主题发现更多涉及这样的类。
class memoize(object):
def __init__(self, cls):
self.cls = cls
# I didn't understand why this was needed
self.__dict__.update(cls.__dict__)
# bit about static methods not needed
def __call__(self, *args):
try:
self.cls.instances
except:
self.cls.instances = {}
key = '//'.join(map(str, args))
if key not in self.cls.instances:
self.cls.instances[key] = self.cls(*args)
return self.cls.instances[key]
class Foo():
def __init__(self,val):
self.val = val
def __repr__(self):
return "{}<{},{}>".format(self.__class__.__name__,self.val,id(self))
class Bar(Foo):
def __init__(self,val):
super().__init__(val)
f1,f2,f3 = [Foo(i) for i in (0,0,1)]
print([f1,f2,f3])
b1,b2,b3 = [Bar(i) for i in (0,0,1)]
print([b1,b2,b3])
# produces exactly what I expect
# [Foo<0,3071981964>, Foo<0,3071982092>, Foo<1,3071982316>]
# [Bar<0,3071983340>, Bar<0,3071983404>, Bar<1,3071983436>]
Foo = memoize(Foo)
f1,f2,f3 = [Foo(i) for i in (0,0,1)]
print([f1,f2,f3])
b1,b2,b3 = [Bar(i) for i in (0,0,1)]
print([b1,b2,b3])
# and now Foo has been memoized so Foo(0) always produces the same object
# [Foo<0,3071725804>, Foo<0,3071725804>, Foo<1,3071726060>]
# [Bar<0,3071711916>, Bar<0,3071711660>, Bar<1,3071725644>]
# this produces a compilation error that I don't understand
class Baz(Foo):
def __init__(self,val):
super().__init__(val)
# Traceback (most recent call last):
# File "/tmp/foo.py", line 49, in <module>
# class Baz(Foo):
# TypeError: __init__() takes 2 positional arguments but 4 were given
答案 0 :(得分:0)
这个&#34;食谱&#34;确实是一个非常糟糕的主意 - 一旦你将Foo
重新绑定到memoize(Foo)
,Foo
就是memoize
个实例,而不再是Foo
类。这打破了所有期望wrt / python&#39; type
和整个对象模型。在这种情况下,它是关于class
语句如何工作的。实际上,这个:
class Titi():
x = 42
def toto(self):
print(self.x)
是语法糖:
def toto(self):
print(self.x)
Titi = type("Titi", (object,), {x:42, toto:toto})
del toto
请注意,这在运行时发生(就像Python中除了解析/字节码编译之外的所有内容),并且type
是一个类,因此调用type
会创建一个新类type
实例(这被命名为&#39;元类&#39; - 类的类 - 而type
是默认的元类)。
因此,Foo
现在是memoize
个实例,而不是Type
个实例,因为memoize
不是一个合适的元类(它是{{1}方法签名是不兼容的),整件事情都行不通。
要使这一点发挥作用,您必须使__init__
成为一个合适的元类(这是一个简单的例子,假设一个名为memoize
的arg,但如果你想要它可以推广):
param