我使用的是python3,我发现我不能在元类的__call__
内使用super()
。在
为什么在下面的代码中super()
引发TypeError: 'ListMetaclass' object is not iterable
异常?为什么我从元类中删除__call__
方法会很好地工作?在
class ListMetaclass(type):
def __new__(cls, name, bases, attrs):
attrs['add'] = lambda self, value: self.append(value)
new_cls = type.__new__(cls, name, bases, attrs)
return new_cls
def __call__(cls, *args, **kw):
### why the 'super()' here raises TypeError: 'ListMetaclass' object is not iterable
return super().__call__(cls, *args, **kw)
return super(__class__, cls).__call__(cls, *args, **kw)
return super(__class__, cls.__class__).__call__(cls, *args, **kw)
class MyList(list, metaclass=ListMetaclass):
a=1
def bar(self):
print('test');
L=MyList()
L.add(1)
print('Print MyList :', L)
我知道这会让你困惑,因为你必须把
cls
传递给super().__new__
,但是你不能把它传给super().__call__
。在这是因为}是特殊的。它是behaving like a ^{} :
__call__
是一个普通的方法,而{作为staticmethod,它需要所有参数,而不需要将第一个参数传递给普通方法(它已经绑定)。在
所以把它改成:
在
__call__
内。在使用
super().method
访问超级类的方法将已经将该方法绑定到当前实例。因此方法的self
参数将已经被自动设置,就像调用self.method()
时一样。在因此,当您将当前实例(在本例中是
cls
类型)传递给方法时,实际上是第二次传递它。在所以这最后会打一个电话
__call__(cls, cls, *args, **kw)
。在当您的
^{pr2}$__call__
方法解释这一点时,参数将与以下定义匹配:所以第一个
cls
是正确匹配的,但是第二个cls
被解释为变量参数列表*args
。这里是异常的来源:cls
在需要iterable的地方被传递,但是cls
,类ListMetaclass
,不是iterable。在因此,这里的修复方法只是删除额外的
cls
:super().method()
由于方法绑定已经自动包含了它。在您不应该将}已经被自动传入了。在
cls
传入super().__call__()
;super()
为您处理绑定,因此{您可能被} documentation :
__new__
中的super().__new__(cls, ...)
调用弄糊涂了,这是因为__new__
是这里的例外,请参见^{从
super().__call__(...)
表达式中删除cls
起作用:通过传入}转换为新列表中的值;这要求{}为iterable。在
cls
,实际上是在执行list(cls)
,告诉list()
将{当您移除元类上的
__call__
方法时,当您调用MyClass()
时,将使用默认的type.__call__
方法,该方法只接收常规参数(示例中没有)并返回一个新实例。在相关问题 更多 >
编程相关推荐