Python之__init__()、__new__()、__call__()

本篇用来介绍Python面向对象的思想,以及里边三个核心的方法。

1. __init__()__new__()

示例代码
#  实际上python3里已经可以不用显示地写出继承自Object类了,这里写上python3也不会报错
class A(object):
    def __init__(self):
        print('__init__ function')
        super(A, self).__init__()

    def __new__(cls):
        print('__new__ function')
        self = super(A, cls).__new__(cls)
        return self


if __name__ == '__main__':
    a = A()
输出
__new__ function
__init__ function

从输出结果来看, __new__()先被调用,返回一个实例对象,接着__init__() 被调用。

重点来了:实际上这里边的具体过程是,__new__ ()的返回值就是类的实例对象,这个实例对象会传递给 __init__() 中定义的 self 参数,以便实例对象可以被正确地初始化。

2. __call__()方法

可调用对象包括自定义的函数、内置函数和类。可以通过一个在可调用对象后边加一个()来对其进行调用。可以用callable()判断是否是可调用对象。基于上边那个代码块
a = A()
print(callable(A))
print(callable(a))
输出
__new__ function
__init__ function
True
False
这里之所以实例对象不是可调用对象,是因为类中没有实现__call__()方法。如果在类中实现了 __call__() 方法,那么实例对象也将是一个可调用对象。
同样的代码,加入__call__()方法
class A(object):
    def __init__(self):
        print('__init__ function')
        super(A, self).__init__()

    def __new__(cls):
        print('__new__ function')
        self = super(A, cls).__new__(cls)
        return self
   
    # 这里可以传参,作为可调用对象的参数
    def __call__(self, name):
        print('__call__ function name is %s'%name)


if __name__ == '__main__':
    a = A()
    print(callable(A))
    print(callable(a))
    a('abc')
输出
__new__ function
__init__ function
True
True
__call__ function name is abc
输出说明三个函数的调用顺序是:
__new__()__init__()__call__()
并且,加入__call__()后实例化对象也成为了可调用对象,并且可以通过传参来调用

接下来列举一些关于__call__()的一些例子,代码都是来自于stackoverflow,有了前边的储备,例子很简单,不做解释

class Factorial:
    def __init__(self):
        self.cache = {}
    def __call__(self, n):
        if n not in self.cache:
            if n == 0:
                self.cache[n] = 1
            else:
                self.cache[n] = n * self.__call__(n-1)
        return self.cache[n]

if __name__ == '__main__':
    fact = Factorial()
    for i in range(10):
        print("{}! = {}".format(i, fact(i)))
输出
0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
利用装饰器的思想,计算函数被调用了多少次
class Counter:
    def __init__(self, func):
        self.func = func
        self.count = 0

    def __call__(self, *args, **kwargs):
        self.count += 1
        return self.func(*args, **kwargs)

@Counter
def foo():
    pass


if __name__ == '__main__':
    for i in range(10):
        foo()
    print(foo.count)
输出
10

你可能感兴趣的:(Python之__init__()、__new__()、__call__())