Python __给出错误对象的新方法。uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
为什么下面的代码给出错误Python __给出错误对象的新方法。uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu,python,python-3.x,magic-methods,Python,Python 3.x,Magic Methods,为什么下面的代码给出错误 class Foo: def __new__(cls, *args, **kwargs): print("Creating Instance") instance = super(Foo, cls).__new__(cls,*args, **kwargs) return instance def __init__(self, a, b): self.a = a self.b
class Foo:
def __new__(cls, *args, **kwargs):
print("Creating Instance")
instance = super(Foo, cls).__new__(cls,*args, **kwargs)
return instance
def __init__(self, a, b):
self.a = a
self.b = b
z= Foo(2,3)
它给出了以下错误
TypeError: object.__new__() takes exactly one argument (the type to instantiate)
这是正确的。但是,您需要首先删除类引入的参数,这样当最终调用对象时,*args
和**kwargs
都是空的
您的代码应该类似于
class Foo:
def __new__(cls, a, b, *args, **kwargs):
print("Creating Instance")
instance = super(Foo, cls).__new__(cls, *args, **kwargs)
return instance
def __init__(self, a, b, *args, **kwargs):
super().__init__(*args, **kwargs)
self.a = a
self.b = b
Foo类:
定义新(cls、a、b、*ARG、**kwargs):
打印(“创建实例”)
实例=super(Foo,cls)。\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
返回实例
定义初始值(self、a、b、*args、**kwargs):
super()
self.a=a
self.b=b
此定义从args
中删除新参数a
和b
,然后将其传递给MRO上的下一位。同样地,对于\uuuuu init\uuuuuuuuuuuuuuuuuu对象,参数是cls
,而不是(cls,*args,**kwargs)对象。
签名是(*args,**kwargs)
,您可以使用inspect.signature函数对此进行检查
但是为什么你会有这个错误呢TLDR:因为您定义了自定义的\uuuuu新方法
小型研究
所有测试都是在Python3.9.1上完成的
考虑下一节课
class-MyClass:
定义初始化(自我):通过
让我们调用对象。\uuuu new\uuuu()
:
>>>对象.uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
没问题。这个类只有自定义的\uuuuuu init\uuuuu
,没有自定义的\uuuuuu new\uuuuuu
现在尝试对您的Foo执行相同的调用:
>>>object.\uuuuuuuuuuuuuuuuo(Foo,*range(10),**{f'a{i}):范围(10)中的i代表i)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
TypeError:object.\uuuuuu new\uuuuuuuu()只接受一个参数(要实例化的类型)
有关对象的异常。\uuuu new\uuuuu()
。这个类既有自定义的\uuuuu init\uuuuu
又有\uuuu new\uuuuu
当仅定义了自定义\uuuuuuuuuuuuuuuuuuu
时,您将看到相同的错误:
>>仅类新建:
... def(cls,*args,**kwargs):返回super()。(cls)
>>>对象.uuuuuuuuuuuuuuuu(OnlyNew,*范围(10),**{f'a{i}):范围(10)中的i代表i)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
TypeError:object.\uuuuuu new\uuuuuuuu()只接受一个参数(要实例化的类型)
让我们检查一个没有自定义\uuuuu init\uuuu
和\uuuu new\uuuu
的类
>A类:合格
>>>对象。uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
TypeError:A()不接受任何参数
完全不同的错误
让我们看看它是如何与继承一起工作的。
从A派生并定义\uuuuu init\uuuu
>>B类(A):
... 定义初始化(自我):通过
>>>对象.uuuuuuuuuuuuuuub,*范围(10),**{f'a{i}:i代表范围(10)中的i)
从MyClass派生,不定义任何内容
>>MC类(MyClass):通过
>>>对象。uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
从MyClass派生并定义\uuuuuu new\uuuuu
>>类子类(MyClass):
def(cls,*args,**kwargs):返回super()。(cls)
>>>对象.uuuuuuuuuuuuuuuuuuuuuu(Sub,*范围(10),**{f'a{i}):范围(10)中的i代表i)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
TypeError:object.\uuuuuu new\uuuuuuuu()只接受一个参数(要实例化的类型)
从Foo派生,不定义任何内容
>F类(Foo):通过
>>>对象.uuuuuuuuuuuuuuuuuuuf,*范围(10),**{F'a{i}:i代表范围(10)中的i)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
TypeError:object.\uuuuuu new\uuuuuuuu()只接受一个参数(要实例化的类型)
现在让我们来看一个非常奇特的案例:
类库:
定义初始化(自我):通过
def(cls,*args,**kwargs):返回super()。(cls)
小类(基本类):
定义初始化(自我):通过
__新建=对象__
免费上课:
定义初始化(自我):通过
__新建=对象__
>>>object.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
>>>对象.uuuuuuuuuuuuuuuuuuuuuu(Sub,*范围(10),**{f'a{i}):范围(10)中的i代表i)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
TypeError:object.\uuuuuu new\uuuuuuuu()只接受一个参数(要实例化的类型)
Sub和Free都没有自定义的\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
方法-在这两个类中\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。但是创建Sub会引发错误,而创建Free则不会。似乎是object.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
结论
如果类的属性中有\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
,则使用>1个参数调用对象会引发TypeError
如果一个类在其MRO中只有自定义的\uuuuu init\uuuuuuu
,而没有自定义的\uuuuuuuu新的
,则调用对象。
和>1个参数将创建一个合适的实例
如果类的MRO中既没有自定义的\uuuuuu init\uuuuu
又没有自定义的\uuuuuu new\uuuuuu
,则调用对象。
带有>1个参数会引发TypeError
是什么让您认为这不应该产生错误?这是一个很好的建议,但我仍然无法理解为什么如果不重写new,那么一切都可以正常工作:new应该得到cls和构造函数参数。如果new没有被覆盖,那么它就是object?它会得到所有这些额外的参数(是吗?),并且从不抱怨,无论显式调用super()。\uuuuunew\uuuuuuuuuuu失败。此外,删除“引入的参数”并不总是可能的。例如,B类
class Foo:
def __new__(cls, a, b, *args, **kwargs):
print("Creating Instance")
instance = super(Foo, cls).__new__(cls, *args, **kwargs)
return instance
def __init__(self, a, b, *args, **kwargs):
super().__init__(*args, **kwargs)
self.a = a
self.b = b