本篇用來介紹Python面向?qū)ο蟮乃枷胝÷颍约袄镞吶齻€核心的方法。
1. __init__()
與__new__()
示例代碼
# 實際上python3里已經(jīng)可以不用顯示地寫出繼承自O(shè)bject類了霎箍,這里寫上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
從輸出結(jié)果來看奇钞, __new__()
先被調(diào)用,返回一個實例對象漂坏,接著__init__()
被調(diào)用景埃。
重點來了:實際上這里邊的具體過程是,__new__ ()
的返回值就是類的實例對象顶别,這個實例對象會傳遞給 __init__()
中定義的 self 參數(shù)谷徙,以便實例對象可以被正確地初始化。
2. __call__()方法
可調(diào)用對象包括自定義的函數(shù)驯绎、內(nèi)置函數(shù)和類完慧。可以通過一個在可調(diào)用對象后邊加一個()
來對其進行調(diào)用剩失∏幔可以用callable()
判斷是否是可調(diào)用對象册着。基于上邊那個代碼塊
a = A()
print(callable(A))
print(callable(a))
輸出
__new__ function
__init__ function
True
False
這里之所以實例對象不是可調(diào)用對象脾歧,是因為類中沒有實現(xiàn)__call__()
方法甲捏。如果在類中實現(xiàn)了 __call__()
方法,那么實例對象也將是一個可調(diào)用對象鞭执。
同樣的代碼摊鸡,加入__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
# 這里可以傳參,作為可調(diào)用對象的參數(shù)
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
輸出說明三個函數(shù)的調(diào)用順序是:
__new__()
蚕冬、__init__()
免猾、__call__()
并且,加入__call__()
后實例化對象也成為了可調(diào)用對象囤热,并且可以通過傳參來調(diào)用
接下來列舉一些關(guān)于__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
利用裝飾器的思想,計算函數(shù)被調(diào)用了多少次
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