本篇用来介绍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