问题一:TypeError: object() takes no parameters

最近在测试 Python 的 __new__ 方法时,我写了如下验证代码

class test(object):
    def __init__(self, a):
        print("this is a init method")
        self.a = a

    def __new__(cls, *args, **kwargs):
        print("this is a new method")
        return super(test, cls).__new__(cls, *args, **kwargs)


t = test(12)
print(t.a)

结果在 Python2 运行正常,在 Python3 却报如下异常

this is a new method
Traceback (most recent call last):
  File "test.py", line 11, in <module>
    t = test(12)
  File "test.py", line 8, in __new__
    return super(test, cls).__new__(cls, *args, **kwargs)
TypeError: object() takes no parameters

一开始是以为 __init__ 拼写错误,或者 tab,spec 混用导致,但是 t = test() 却提示需要传递参数 a

this is a new method
Traceback (most recent call last):
  File "test.py", line 11, in <module>
    t = test()
TypeError: __init__() missing 1 required positional argument: 'a'

那这样就纳闷了,竟然可以找到自己的 __init__ 方法,那为什么还报 no parameters 呢。


这是分割线。后面我查询了很久,在 stackoverflow 找到了回答 https://stackoverflow.com/questions/34777773/typeerror-object-takes-no-parameters-after-defining-new`

下面是 @Blckknght 的回答

In Python 3.3 and later, if you're overriding both __new__ and __init__, you need to avoid passing any extra arguments to the object methods you're overriding. If you only override one of those methods, it's allowed to pass extra arguments to the other one (since that usually happens without your help).

将我的测试代码__new__ 方法部分改成如下

def __new__(cls, *args, **kwargs):
    print("this is a new method")
    return super(test, cls).__new__(cls)   # 不需要传递额外的参数

这样就可以运行成功了。

那我不禁要问,Python3.3+ 到底怎么调用 __init__ 方法的呢,上面的回答也答复了。__init__ 调用是通过 type.__call__,那么 object.__new__ 自然不需要知道 __init__ 的额外参数

感谢 @Blckknght 的回答!!!


Published

Category

python

Tags

Stay in Touch

Friendship Links