__init__
、__new__
和__call__
方法都是python中的魔术方法,通常我们认为__init__
方法是类的构造方法,因为表面上看确实是这样:当需要实例化一个对象的时候,使用a = Class(args...)
便可以返回一个类的实例,其中args参数与__init__
中申明的参数一样,今天在刘志军老师的「Python之禅和朋友们」的知识星球中学习到不是这样的,这里以一个例子来说明一下:
class A:
def __new__(cls, *args, **kwargs):
print('__new__')
print(cls)
print(args)
print('-------')
return super(A, cls).__new__(cls)
def __init__(self):
print('__init__')
print('self is ', self)
self.a, self.b = a, b
a = A(1, 2)
print(a.a)
输出:
__new__
<class '__main__.A'>
(1, 2)
-------
__init__
Traceback (most recent call last):
File "test.py", line 14, in <module>
a = A(1, 2)
TypeError: __init__() takes 1 positional argument but 3 were given
可以看到这里我们并没有直接调用__new__
方法,却先产生了__new__
方法的输出并抛出了异常,所以说__init__
并不是真正意义上的构造方法,__init__
所做的工作是在类的对象创建好之后进行变量的初始化。__new__
方法才会真正创建实例,是类的构造方法。
__call__方法又是干嘛的呢?
Python官方文档中是这样写的:Called when the instance is “called” as a function; if this method is defined, x(arg1, arg2, …) is a shorthand for x.call(arg1, arg2, …).
即实现了__call__
方法的对象的实例就可以像方法、函数一样的被调用执行
class A:
def __call__(self, *args, **kwargs):
print('__call__')
a = A()
a()
输出:__call__