Python中的__init__、__new__和__call__

__init____new____call__方法都是python中的魔术方法,通常我们认为__init__方法是类的构造方法,因为表面上看确实是这样:当需要实例化一个对象的时候,使用a = Class(args...)便可以返回一个类的实例,其中args参数与__init__中申明的参数一样,今天在刘志军老师的「Python之禅和朋友们」的知识星球中学习到不是这样的,这里以一个例子来说明一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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__方法的对象的实例就可以像方法、函数一样的被调用执行

1
2
3
4
5
6
7
8
9
class A:
def __call__(self, *args, **kwargs):
print('__call__')


a = A()
a()

输出:__call__