2017年3月16日 星期四

[Python 文章收集] PYTHON - 進階- FUNCTOOLS 模塊小結

Source From Here
functools.partial
functools.partial 通過包裝手法,允許我們"重新定義" 函數簽名. 用一些默認參數包裝一個可調用對象,返回結果是可調用對象,並且可以像原始對像一樣對待. 凍結部分函數位置函數或關鍵字參數,簡化函數,更少更靈活的函數參數調用:
  1. def partial(func, *args, **keywords):  
  2.     def newfunc(*fargs, **fkeywords):  
  3.         newkeywords = keywords.copy()  
  4.         newkeywords.update(fkeywords)  
  5.         return func(*(args + fargs), **newkeywords)  
  6.     newfunc.func = func  
  7.     newfunc.args = args  
  8.     newfunc.keywords = keywords  
  9.     return newfunc  
一個簡單範例如下:
>>> import functools
>>> def add(a, b): return a + b
...
>>> add(4, 2)
6
>>> plus3 = functools.partial(add, 3)
>>> plus5 = functools.partial(add, 5)
>>> plus3(4)
7
>>> plus3(7)
10
>>> plus5(10)
15

應用: 典型的,函數在執行時,要帶上所有必要的參數進行調用。然後,有時參數可以在函數被調用之前提前獲知。這種情況下,一個函數有一個或多個參數預先就能用上,以便函數能用更少的參數進行調用。

functool.update_wrapper
默認 partial 對像沒有 __name__ 和 __doc__ , 這種情況下,對於裝飾器函數非常難以 debug.使用 update_wrapper() , 從原始對象拷貝或加入現有 partial 對象 它可以把被封裝函數的 __name__、module、 __doc__ 和 __dict__ 都複製到封裝函數去(模塊級別常量WRAPPER_ASSIGNMENTS, WRAPPER_UPDATES):
>>> functools.WRAPPER_ASSIGNMENTS
('__module__', '__name__', '__doc__')

這個函數主要用在裝飾器函數中,裝飾器返回函數反射得到的是包裝函數的函數定義而不是原始函數定義. 一個使用範例如下:
  1. #!/usr/bin/env python  
  2.   
  3. def wrap(func):  
  4.     def call_it(*args, **kwargs):  
  5.         """Wrap func: call_it """  
  6.         print "Before call"  
  7.         return func(*args, **kwargs)  
  8.     return call_it  
  9.   
  10. @wrap  
  11. def hello():  
  12.     """Say hello """  
  13.     print "Hello World"  
  14.   
  15. from functools import update_wrapper  
  16. def wrap2(func):  
  17.     def call_it(*args, **kwargs):  
  18.         """Wrap func: call_it2"""  
  19.         print "Before call"  
  20.         return func(*args, **kwargs)  
  21.     return update_wrapper(call_it, func)  
  22.   
  23. @wrap2  
  24. def hello2():  
  25.     """ Test hello"""  
  26.     print "Hello World2"  
  27.   
  28. if __name__ == '__main__':  
  29.     hello()  
  30.     print hello.__name__  
  31.     print hello.__doc__  
  32.     print  
  33.     hello2()  
  34.     print hello2.__name__  
  35.     print hello2.__doc__  
執行結果:
Before call
Hello World
call_it
Wrap func: call_it

Before call
Hello World2
hello2
Test hello

functool.wraps
調用函數裝飾器 partial(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated) 的簡寫, 來看一個簡單範例:
  1. from functools import wraps  
  2. def wrap3(func):  
  3.     @wraps(func)  
  4.     def call_it(*args, **kwargs):  
  5.         """Wrap func: call_it2"""  
  6.         print "Before call"  
  7.         return func(*args, **kwargs)  
  8.     return call_it  
  9.   
  10. @wrap3  
  11. def hello3():  
  12.     """ Test hello 3"""  
  13.     print "Hello World3"  
  14.   
  15. if __name__ == '__main__':  
  16.     hello3()  
  17.     print hello3.__name__  
  18.     print hello3.__doc__  
執行結果:
Before call
Hello World3
hello3
Test hello 3

functools.reduce
此函數等同於內置函數 reduce() . 用這個的原因是使代碼更兼容 (python3)

functools.cmp_to_key
將老式的比較函數(comparison function)轉化為關鍵字函數(key function)。與接受 key function 的工具一同使用(如 sorted()min()max()heapq.nlargest()itertools.groupby())。該函數主要用來將程序轉成 Python 3 格式的,因為 Python 3 中不支持比較函數。比較函數是可調用的,接受兩個參數,比較這兩個參數並根據他們的大小關係返回負值、零或正值中的某一個。關鍵字函數也是可調用的,接受一個參數,同時返回一個可以用作排序關鍵字的值。
  1. import functools  
  2.   
  3. class People(object):  
  4.     def __init__(self, name, age):  
  5.         self.name = name  
  6.         self.age = age  
  7.   
  8.     def __str__(self):  
  9.         return "%s (%d)" % (self.name, self.age)  
  10.   
  11. p_list = []  
  12. p_list.append(People('John'36))  
  13. p_list.append(People('Mark'20))  
  14. p_list.append(People('Ken'30))  
  15. p_list.append(People('Peter'28))  
  16.   
  17. print "Without sorting:"  
  18. for p in p_list:  
  19.     print "\t%s" % (p)  
  20. print  
  21.   
  22. print "Sorting with age:"  
  23. for p in sorted(p_list, key=lambda p: p.age):  
  24.     print "\t%s" % (p)  
  25. print  
  26.   
  27. print "Sorting with name:"  
  28. for p in sorted(p_list, key=lambda p: p.name):  
  29.     print "\t%s" % (p)  
  30. print  
執行結果:
Without sorting:
John (36)
Mark (20)
Ken (30)
Peter (28)

Sorting with age:
Mark (20)
Peter (28)
Ken (30)
John (36)

Sorting with name:
John (36)
Ken (30)
Mark (20)
Peter (28)

functools.total_ordering
這是一個 類裝飾器,給定一個類,這個類定義了一個或多個比較排序方法,這個類裝飾器將會補充其餘的比較方法,減少了自己定義所有比較方法時的工作量。被修飾的類必須至少定義 __lt__()__le__()__gt__() 或 __ge__() 中的一個,同時,被修飾的類還應該提供 __eq__() 方法。一個簡單範例如下:
  1. from functools import total_ordering  
  2.   
  3. @total_ordering  
  4. class People(object):  
  5.     def __init__(self, name, age):  
  6.         self.name = name  
  7.         self.age = age  
  8.   
  9.     def __str__(self):  
  10.         return "%s (%d)" % (self.name, self.age)  
  11.   
  12.     def __eq__(self, op):  
  13.         return self.age == op.age and self.name == op.name  
  14.   
  15.     def __lt__(self, op):  
  16.         if self.name == op.name:  
  17.             return self.age < op.age  
  18.         else:  
  19.             return self.name < op.name  
  20.   
  21. p1 = People("Ken"27)  
  22. p2 = People("Ken"27)  
  23.   
  24. print "%s < %s? %s" % (p1, p2, p1 < p2)  
  25. print "%s > %s? %s" % (p1, p2, p1 > p2)  
  26. print "%s <= %s? %s" % (p1, p2, p1 <= p2)  
  27. print "%s >= %s? %s" % (p1, p2, p1 >= p2)  
  28. print "%s == %s? %s" % (p1, p2, p1==p2)  
執行結果:
Ken (27) < Ken (27)? False
Ken (27) > Ken (27)? False
Ken (27) <= Ken (27)? True
Ken (27) >= Ken (27)? True
Ken (27) == Ken (27)? True


沒有留言:

張貼留言

[Git 常見問題] error: The following untracked working tree files would be overwritten by merge

  Source From  Here 方案1: // x -----删除忽略文件已经对 git 来说不识别的文件 // d -----删除未被添加到 git 的路径中的文件 // f -----强制运行 #   git clean -d -fx 方案2: 今天在服务器上  gi...