为什么以下代码给出错误?
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)
答案 0 :(得分:5)
instance = super(Foo, cls).__new__(cls,*args, **kwargs)
是正确的。但是,您负责首先删除您的类引入的参数,以便最终调用object.__new__
时,*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
此定义将您的新参数a
和b
从args
中删除,然后再将其传递给MRO上的下一个。 __init__
也是如此。
答案 1 :(得分:5)
object.__new__()
签名为 (*args, **kwargs)
,您可以使用 inspect.signature
函数检查。
但是为什么会出现这个错误呢? TLDR:因为您定义了自定义 __new__
方法。
所有测试均在 Python 3.9.1 上完成。
考虑下一节课。
class MyClass:
def __init__(self): pass
让我们调用 object.__new__()
:
>>> object.__new__(MyClass, *range(10), **{f'a{i}': i for i in range(10)})
<__main__.MyClass object at 0x000001E7B15B3550>
完全没有问题。此类只有自定义 __init__
,没有自定义 __new__
。
现在尝试为您的 Foo 执行相同的调用:
>>> object.__new__(Foo, *range(10), **{f'a{i}': i for i in range(10)})
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: object.__new__() takes exactly one argument (the type to instantiate)
关于 object.__new__()
的异常。此类具有自定义 __init__
和 __new__
。
当仅定义自定义 __new__
时,您将看到相同的错误:
>>> class OnlyNew:
... def __new__(cls, *args, **kwargs): return super().__new__(cls)
>>> object.__new__(OnlyNew, *range(10), **{f'a{i}': i for i in range(10)})
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: object.__new__() takes exactly one argument (the type to instantiate)
让我们检查一个没有自定义 __init__
和 __new__
的类。
>>> class A: pass
>>> object.__new__(A, *range(10), **{f'a{i}': i for i in range(10)})
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: A() takes no arguments
完全不同的错误。
让我们来看看它是如何与继承一起工作的。
从 A 派生并定义 __init__
。
>>> class B(A):
... def __init__(self): pass
>>> object.__new__(B, *range(10), **{f'a{i}': i for i in range(10)})
<__main__.B object at 0x000001E7B15D23A0>
从 MyClass 派生并定义任何内容。
>>> class MC(MyClass): pass
>>> object.__new__(MC, *range(10), **{f'a{i}': i for i in range(10)})
<__main__.MC object at 0x000001E7B15D2CA0>
从 MyClass 派生并定义 __new__
。
>>> class Sub(MyClass):
def __new__(cls, *args, **kwargs): return super().__new__(cls)
>>> object.__new__(Sub, *range(10), **{f'a{i}': i for i in range(10)})
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: object.__new__() takes exactly one argument (the type to instantiate)
从 Foo 派生,什么都不定义。
>>> class F(Foo): pass
>>> object.__new__(F, *range(10), **{f'a{i}': i for i in range(10)})
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: object.__new__() takes exactly one argument (the type to instantiate)
现在让我们看一个绝对奇特的案例:
class Base:
def __init__(self): pass
def __new__(cls, *args, **kwargs): return super().__new__(cls)
class Sub(Base):
def __init__(self): pass
__new__ = object.__new__
class Free:
def __init__(self): pass
__new__ = object.__new__
>>> object.__new__(Free, *range(10), **{f'a{i}': i for i in range(10)})
<__main__.Free object at 0x000001E7B15C5A90>
>>> object.__new__(Sub, *range(10), **{f'a{i}': i for i in range(10)})
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: object.__new__() takes exactly one argument (the type to instantiate)
Sub 和 Free 都没有自定义的 __new__
方法 - 在两个类中 __new__
都是 object.__new__()
。但是创建 Sub 会引发错误,而创建 Free 不会。似乎 object.__new__()
检查的不是 getattr(A_Class, '__new__', object.__new__) is object.__new__
而是 all(getattr(cls, '__new__', object.__new__) is object.__new__ for cls in A_Class.mro())
。
__new__
,则使用 >1 个参数调用 object.__new__()
会引发 TypeError。__init__
并且其 MRO 中没有自定义 __new__
,则使用 >1 个参数调用 object.__new__()
会创建一个正确的实例。__init__
和 __new__
,则使用 >1 个参数调用 object.__new__()
会引发 TypeError。答案 2 :(得分:1)
object.__new__(cls)
,参数是cls
,不是(cls, *args, **kwargs)