Python 为什么在元类的_调用_方法中使用super()会引发TypeError?
我使用的是Python3,我发现我不能在元类的Python 为什么在元类的_调用_方法中使用super()会引发TypeError?,python,python-3.x,super,metaclass,Python,Python 3.x,Super,Metaclass,我使用的是Python3,我发现我不能在元类的\uu调用
\uu调用
中使用super()
为什么在下面的代码中,super()
会引发TypeError:“ListMetaclass”对象不可编辑
异常?如果我从元类中删除\uuuu call\uuu
方法,为什么它工作得很好
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()。\uuuuu call\uuuuu()
super()
负责为您进行绑定,因此cls
已自动传入
您可能被super().\uuuu new\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu(cls,…)
调用\u;这是因为\uuuu new\uuuu
是这里的例外,请参阅:
调用以创建类cls的新实例__new_u()
是一个静态方法(有特殊的大小写,因此不需要声明),它将请求实例的类作为其第一个参数
从super()中删除cls
。\uuuu调用\uuuuuu(…)
表达式起作用:
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):
return super().__call__(*args, **kw)
通过传入cls
,可以有效地执行list(cls)
,告诉list()
将cls
转换为新列表中的值;这要求cls
成为一个可编辑的
当您删除元类上的\uuuuu call\uuuu
方法时,当您调用MyClass()
时,将使用默认的类型。
方法,该方法只接收正常参数(在您的示例中没有)并返回一个新实例。使用super()访问超类的方法.method
将已将该方法绑定到当前实例。因此,方法的self
参数将自动设置,就像调用self.method()
时一样
因此,当您将当前实例(在本例中为cls
类型)传递给该方法时,实际上是在第二次传递它
super().__call__(cls, *args, **kw)
因此,这将结束一个调用\uuuuuuuuuuuuuuuu调用(cls,cls,*args,**kw)
然后,当您的\uuuu调用\uuuu
方法对其进行解释时,参数将与以下定义相匹配:
def __call__(cls, *args, **kw):
因此,第一个cls
正确匹配,但第二个cls
被解释为变量参数列表*args
。这里是异常的来源:cls
在需要iterable的地方传递,但是类ListMetaclass
不可iterable
因此,这里的修复方法只是删除额外的cls
:super()。由于方法绑定,method()
将自动包含它。我可以看出这会让人困惑,因为您必须将cls
传递给super()。\uuu new\uuu
但您不能将它传递给super().\uuuu调用\uuuu
这是因为\uuuuu call\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
是一种正常的方法,而\uuuuuuuuu。它是:
object.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
调用以创建类cls
的新实例\uuuu new\uuuuu()
是一个静态方法(特殊情况下,您不需要这样声明)[…]
作为staticmethod,它需要所有参数,而不需要将第一个参数传递给普通方法(它已经绑定)
因此,只需将其更改为:
return super().__call__(*args, **kw)
内部调用