万物之中, 希望至美.

Python中的__init__、__new__和__call__

2018.02.01

__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__
comments powered by Disqus