Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么在元类的_调用_方法中使用super()会引发TypeError?_Python_Python 3.x_Super_Metaclass - Fatal编程技术网

Python 为什么在元类的_调用_方法中使用super()会引发TypeError?

Python 为什么在元类的_调用_方法中使用super()会引发TypeError?,python,python-3.x,super,metaclass,Python,Python 3.x,Super,Metaclass,我使用的是Python3,我发现我不能在元类的\uu调用

我使用的是Python3,我发现我不能在元类的
\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)
内部调用