Python Tips閱讀摘要

發(fā)現(xiàn)了一本關(guān)于Python精通知識點(diǎn)的好書《Python Tips》,關(guān)于Python的進(jìn)階的技巧。摘錄一些比較有價值的內(nèi)容作為分享。

*args and **kwargs

在函數(shù)定義的時候我們經(jīng)??吹?args和 *kwargs這兩個定義對象。*args代表了函數(shù)定義中所有non-keyworded(這個詞實(shí)在很難翻譯)的傳入?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(猴子補(bǔ)?。?,用來在運(yùn)行時動態(tài)修改已有的代碼,而不需要修改原始代碼。

  • monkey patching
    monkey patch指的是在運(yùn)行時動態(tài)替換,一般是在startup的時候.
    用過gevent就會知道,會在最開頭的地方gevent.monkey.patch_all();把標(biāo)準(zhǔn)庫中的thread/socket等給替換掉.這樣我們在后面使用socket的時候可以跟平常一樣使用,無需修改任何代碼,但是它變成非阻塞的了.
    應(yīng)用場景包括,一個已經(jīng)定義好的函數(shù)被大量的引用,如果后面需要替換這個函數(shù)的話,直接在函數(shù)入口處進(jìn)行替換即可。舉個栗子,將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__

可以看到j(luò)son在該模塊中被完美替換,這個方法也可以用來做單元測試使用。

Generators生成器

首先區(qū)分Iterable、Iterator和Iteration三個概念:任何具有iter()或getitem()方法的對象,Python就認(rèn)為它是一個iterable;使用內(nèi)置的iter()函數(shù)來生成iterator,iterator可以通過next()方法來獲取下一個元素。iterator遍歷元素的過程可以認(rèn)為iteration。
生成器同樣是可迭代對象,但是你只能讀取一次,因?yàn)樗]有把所有值存放內(nèi)存中,它動態(tài)的生成值。
Yield是關(guān)鍵字, 用起來像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))
當(dāng)時這兩者還可以通過lambda表達(dá)式進(jìn)行多個函數(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ù)都進(jìn)行處理,并返回在了結(jié)果中。

  • filter

filter(function_to_apply, list_of_inputs)

在大部分的情況下map和filter都可以通過list/dict/tuple Comprehensions來實(shí)現(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做運(yùn)算后,繼續(xù)循環(huán),expr運(yùn)算得到的值賦給變量L

map

map(function_to_apply, list_of_inputs)

通過函數(shù)對于結(jié)果進(jìn)行處理,并返回聚集結(jié)果。例如:

from functools import reduce
product = reduce((lambda x, y: x * y), [1, 2, 3, 4])

# Output: 24

Collections

Collections包括幾個常用的數(shù)據(jù)結(jié)構(gòu):

  • defaultdict : 是dict的子類,實(shí)現(xiàn)了dict的所有方法,功能使用上與dict.setdefault()類似,但是defaultdict構(gòu)建時給出默認(rèn)值。
  • orderdict:dict自排序。
  • counter:計數(shù)器,可以對iterator計數(shù),也可以對list計數(shù)。
  • deque:隊列。
  • nametuple:繼承自tuple,我認(rèn)為本質(zhì)上是快速創(chuàng)建僅包括屬性的類對象,從這個角度上看非常實(shí)用。
  • enum:枚舉類型,但是必須注意,枚舉成員本身類型就是枚舉類型,因此如果需要將枚舉成員用以讀寫及比較操作將會報錯。
    這篇教程中還講了一些協(xié)程coroutine、異步IO的概念,但都屬于技巧性的內(nèi)容,講的不透徹就不再一一分享。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容