一:callablespython
callables使類實例可以像函數同樣被調用
若是類須要一個函數型接口這時用callable,最好繼承自abc.Callable,這樣有些檢查機制而且一看就知道此類的目的是callable對象
若是類須要有‘記憶’功能,使用callable是很是方便的相對於函數而言,callable語法什麼的就要複雜多了,這也是其主要的缺點:
def x(args):
body
轉化爲callable對象:
class X(collections.abc.callable):
def __call__(self, args):
body
x= X()
1:計算x^y
1 import collections.abc #注,徹底能夠不引入cleection.abc,引入是爲了可以作一些錯誤檢查 2 class Power1( collections.abc.Callable ): 3 def __call__( self, x, n ): 4 p= 1 5 for i in range(n): 6 p *= x 7 return p 8 9 power= Power1() 10 >>> power( 2, 0 ) #像函數同樣調用實例 11 1 12 >>> power( 2, 1 ) 13 2 14 >>> power( 2, 2 ) 15 4 16 >>> power( 2, 10 ) 17 1024 18 19 # 提高性能:上面是O(n),用遞歸改進爲O(logn) 20 class Power4( abc.Callable ): 21 def __call__( self, x, n ): 22 if n == 0: 23 return 1 24 elif n % 2 == 1: 25 return self.__call__(x, n-1)*x 26 else: 27 t= self.__call__(x, n//2) 28 return t*t 29 30 pow4= Power4() 31 32 # 再次提高性能,使用記憶功能【注:能夠{(2,4):16,... } 33 class Power5( collections.abc.Callable ): 34 def __init__( self ): 35 self.memo = {} 36 def __call__( self, x, n ): 37 if (x,n) not in self.memo: 38 if n == 0: 39 self.memo[x,n]= 1 40 elif n % 2 == 1: 41 self.memo[x,n]= self.__call__(x, n-1) * x 42 elif n % 2 == 0: 43 t= self.__call__(x, n//2) 44 self.memo[x,n]= t*t 45 else: 46 raise Exception("Logic Error") 47 return self.memo[x,n] 48 49 pow5= Power5() 50 51 # 再次改進,python庫自帶了一個記憶裝飾器,可使用這個從而不不用自定義callable對象 52 from functools import lru_cache 53 @lru_cache(None) 54 def pow6( x, n ): 55 if n == 0: 56 return 1 57 elif n % 2 == 1: 58 return pow6(x, n-1)*x 59 else: 60 t= pow6(x, n//2) 61 return t*t 62 # Previous requests are stored in a memoization cache. The requests are 63 # tracked in the cache, and the size is limited. The idea behind an LRU cache is that 64 # the most recently made requests are kept and the least recently made requests are quietly purged.
2:賭注翻倍:綜合運用callables,輸家翻倍賭注政策:每輸一次後賭注就加倍直到贏了後迴歸本來賭注ide
1 class BettingMartingale( BettingStrategy ): 2 def __init__( self ): 3 self._win= 0 4 self._loss= 0 5 self.stage= 1 6 @property 7 def win(self): 8 return self._win 9 @win.setter 10 def win(self, value): 11 self._win = value 12 self.stage= 1 13 @property 14 def loss(self): 15 return self._loss 16 @loss.setter 17 def loss(self, value): 18 self._loss = value 19 self.stage *= 2 20 21 def __call__( self ): 22 return self.stage 23 24 >>> bet= BettingMartingale() 25 >>> bet() 26 1 27 >>> bet.win += 1 28 >>> bet() 29 1 30 >>> bet.loss += 1 31 >>> bet() 32 2 33 34 # property的使用使類的定義顯得冗雜,實際上咱們只關心setters,因此咱們用__setattr__來改進上述版本 35 class BettingMartingale2( BettingStrategy ): 36 def __init__( self ): 37 self.win= 0 38 self.loss= 0 39 self.stage= 1 40 def __setattr__( self, name, value ): 41 if name == 'win': 42 self.stage = 1 43 elif name == 'loss': 44 self.stage *= 2 45 super().__setattr__( name, value ) 46 def __call__( self ): 47 return self.stage
二:context
A context is generally used to acquire/release, open/close, and lock/unlock types of operation pairs.
Most of the examples are file I/O related, and most of the file-like objects in Python are already proper context managers.
1:一些context
1:最多見的是用在文件的,with語句建立
2:decimal context:decimal是一個模塊,經常使用於一些對於精度要求比較嚴格的計算,其自己運行在一個context中,經過改context能夠對全局的計算產生影響
3:還有一些context,主要都是用於類文件的操做
2:構造context(第八章會詳細講解構造context)
context最主要的是有__enter__()與__exit__()方法,分別在with語句開始和結束時調用
拋出的問題都會以traceback參數傳遞到__exit__()函數中,應該作相應處理。
例子:錯誤處理context:在打開文件時作備份,若處理完文件沒出問題就刪除備份,若出了問題就使用備份來恢復原文件
1 import os 2 class Updating: 3 def __init__( self, filename ): 4 self.filename= filename 5 def __enter__( self ): #作文件備份 6 try: 7 self.previous= self.filename+" copy" 8 os.rename( self.filename, self.previous ) 9 except FileNotFoundError: 10 # Never existed, no previous copy 11 self.previous= None 12 13 def __exit__( self, exc_type, exc_value, traceback ): # 14 if exc_type is not None: 15 try: 16 os.rename( self.filename, self.filename+ " error" ) 17 except FileNotFoundError: 18 pass # Never even got created? 19 if self.previous: 20 os.rename( self.previous, self.filename ) #用備份文件恢復原文件 21 22 with Updating( "some_file" ): 23 with open( "some_file", "w" ) as target: 24 process( target )