發(fā)現(xiàn)了一本關于Python精通知識點的好書《Python Tips》截碴,關于Python的進階的技巧汹胃。摘錄一些比較有價值的內(nèi)容作為分享鸟妙。
*args and **kwargs
在函數(shù)定義的時候我們經(jīng)撑铮看到*args和 *kwargs這兩個定義對象。*args代表了函數(shù)定義中所有non-keyworded(這個詞實在很難翻譯)的傳入?yún)?shù)芍锚,而*kwargs代表的所有帶有keyworded的傳入?yún)?shù),舉個栗子:
def test_var_args(*args, **kwargs):
print("args:{0}, kwargs:{1}".format(args,kwargs))
test_var_args(1,2,3)
>>>args:(1, 2, 3), kwargs:{}
test_var_args(a=1,b=2,c=3)
>>>args:(), kwargs:{'a': 1, 'c': 3, 'b': 2}
通過這個栗子我們可以清晰地區(qū)分keyworded和non-keyworded的區(qū)別了蔓榄。本質(zhì)上來說并炮,args是一個數(shù)組,kwargs是一個字典甥郑。
args and *kwargs 最常用于裝飾器逃魄,也可以用于monkey patching(猴子補丁)澜搅,用來在運行時動態(tài)修改已有的代碼伍俘,而不需要修改原始代碼。
- monkey patching
monkey patch指的是在運行時動態(tài)替換,一般是在startup的時候.
用過gevent就會知道,會在最開頭的地方gevent.monkey.patch_all();把標準庫中的thread/socket等給替換掉.這樣我們在后面使用socket的時候可以跟平常一樣使用,無需修改任何代碼,但是它變成非阻塞的了.
應用場景包括店展,一個已經(jīng)定義好的函數(shù)被大量的引用养篓,如果后面需要替換這個函數(shù)的話,直接在函數(shù)入口處進行替換即可赂蕴。舉個栗子柳弄,將ujson代替json:
main.py
import json
import ujson
def monkey_patch_json():
json.__name__ = 'ujson'
json.dumps = ujson.dumps
json.loads = ujson.loads
monkey_patch_json()
print 'main.py',json.__name__
import sub
======================
sub.py
import json
print 'sub.py',json.__name__
可以看到json在該模塊中被完美替換,這個方法也可以用來做單元測試使用概说。
Generators生成器
首先區(qū)分Iterable碧注、Iterator和Iteration三個概念:任何具有iter()或getitem()方法的對象,Python就認為它是一個iterable糖赔;使用內(nèi)置的iter()函數(shù)來生成iterator萍丐,iterator可以通過next()方法來獲取下一個元素。iterator遍歷元素的過程可以認為iteration放典。
生成器同樣是可迭代對象逝变,但是你只能讀取一次基茵,因為它并沒有把所有值存放內(nèi)存中,它動態(tài)的生成值壳影。
Yield是關鍵字拱层, 用起來像return,yield在告訴程序宴咧,要求函數(shù)返回一個生成器根灯,舉個栗子:
def createGenerator():
my_list=range(3)
for i in my_list:
yield i*i
gen= createGenerator()
print(next(gen))
print(next(gen))
print(next(gen))
print(next(gen)) #StopIteration
Map, Filter and Reduce
- map
Map的定義是將某函數(shù)處理所有輸入?yún)?shù),其定義為:
map(function_to_apply, list_of_inputs)
例如:
items = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x**2, items))
當時這兩者還可以通過lambda表達式進行多個函數(shù)處理同一個輸入的情況掺栅,這是一個非常美妙的轉(zhuǎn)換烙肺,栗子如下:
def multiply(x):
return (x*x)
def add(x):
return (x+x)
funcs = [multiply, add]
for i in range(5):
value = list(map(lambda x: x(i), funcs))
print(value)
# Output:
# [0, 0]
# [1, 2]
# [4, 4]
# [9, 6]
# [16, 8]
神奇的事情發(fā)生了,兩個函數(shù)對于同一個輸入?yún)?shù)都進行處理氧卧,并返回在了結果中桃笙。
- filter
filter(function_to_apply, list_of_inputs)
在大部分的情況下map和filter都可以通過list/dict/tuple Comprehensions來實現(xiàn)。
List Comprehensions語法:[expr for iter_var in iterable] 或 [expr for iter_var in iterable if cond_expr]
L = [expr for iter_var in iterable]:for iter_var in iterable的作用是依次取 iterable賦值給iter_var假抄,而expr for iter_var in iterable的作用就是依次取值給iter_var怎栽,expr做運算后,繼續(xù)循環(huán)宿饱,expr運算得到的值賦給變量L
map
map(function_to_apply, list_of_inputs)
通過函數(shù)對于結果進行處理熏瞄,并返回聚集結果。例如:
from functools import reduce
product = reduce((lambda x, y: x * y), [1, 2, 3, 4])
# Output: 24
Collections
Collections包括幾個常用的數(shù)據(jù)結構:
- defaultdict : 是dict的子類谬以,實現(xiàn)了dict的所有方法强饮,功能使用上與dict.setdefault()類似,但是defaultdict構建時給出默認值为黎。
- orderdict:dict自排序邮丰。
- counter:計數(shù)器,可以對iterator計數(shù)铭乾,也可以對list計數(shù)剪廉。
- deque:隊列。
- nametuple:繼承自tuple炕檩,我認為本質(zhì)上是快速創(chuàng)建僅包括屬性的類對象斗蒋,從這個角度上看非常實用。
- enum:枚舉類型笛质,但是必須注意泉沾,枚舉成員本身類型就是枚舉類型,因此如果需要將枚舉成員用以讀寫及比較操作將會報錯妇押。
這篇教程中還講了一些協(xié)程coroutine跷究、異步IO的概念,但都屬于技巧性的內(nèi)容敲霍,講的不透徹就不再一一分享俊马。