Python Tips閱讀摘要

發現了一本關於Python精通知識點的好書《Python Tips》,關於Python的進階的技巧。摘錄一些比較有價值的內容做爲分享。html

*args and **kwargs

在函數定義的時候咱們常常看到*args和 **kwargs這兩個定義對象。*args表明了函數定義中全部non-keyworded(這個詞實在很難翻譯)的傳入參數,而**kwargs表明的全部帶有keyworded的傳入參數,舉個栗子:python

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}

經過這個栗子咱們能夠清晰地區分keyworded和non-keyworded的區別了。本質上來講,args是一個數組,kwargs是一個字典。
args and *kwargs 最經常使用於裝飾器,也能夠用於monkey patching(猴子補丁),用來在運行時動態修改已有的代碼,而不須要修改原始代碼。json

  • monkey patching
    monkey patch指的是在運行時動態替換,通常是在startup的時候.
    用過gevent就會知道,會在最開頭的地方gevent.monkey.patch_all();把標準庫中的thread/socket等給替換掉.這樣咱們在後面使用socket的時候能夠跟日常同樣使用,無需修改任何代碼,可是它變成非阻塞的了.
    應用場景包括,一個已經定義好的函數被大量的引用,若是後面須要替換這個函數的話,直接在函數入口處進行替換便可。舉個栗子,將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生成器

首先區分Iterable、Iterator和Iteration三個概念:任何具備__iter__()或__getitem__()方法的對象,Python就認爲它是一個iterable;使用內置的iter()函數來生成iterator,iterator能夠經過__next__()方法來獲取下一個元素。iterator遍歷元素的過程能夠認爲iteration。
生成器一樣是可迭代對象,可是你只能讀取一次,由於它並無把全部值存放內存中,它動態的生成值。
Yield是關鍵字, 用起來像return,yield在告訴程序,要求函數返回一個生成器,舉個栗子:數據結構

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的定義是將某函數處理全部輸入參數,其定義爲:

    map(function_to_apply, list_of_inputs)app

例如:異步

items = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x**2, items))
當時這二者還能夠經過lambda表達式進行多個函數處理同一個輸入的狀況,這是一個很是美妙的轉換,栗子以下:socket

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]

神奇的事情發生了,兩個函數對於同一個輸入參數都進行處理,並返回在告終果中。函數

  • filter

    filter(function_to_apply, list_of_inputs)單元測試

在大部分的狀況下map和filter均可以經過list/dict/tuple Comprehensions來實現。
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作運算後,繼續循環,expr運算獲得的值賦給變量L

map

map(function_to_apply, list_of_inputs)

經過函數對於結果進行處理,並返回彙集結果。例如:

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

# Output: 24

Collections

Collections包括幾個經常使用的數據結構:

  • defaultdict : 是dict的子類,實現了dict的全部方法,功能使用上與dict.setdefault()相似,可是defaultdict構建時給出默認值。
  • orderdict:dict自排序。
  • counter:計數器,能夠對iterator計數,也能夠對list計數。
  • deque:隊列。
  • nametuple:繼承自tuple,我認爲本質上是快速建立僅包括屬性的類對象,從這個角度上看很是實用。
  • enum:枚舉類型,可是必須注意,枚舉成員自己類型就是枚舉類型,所以若是須要將枚舉成員用以讀寫及比較操做將會報錯。 這篇教程中還講了一些協程coroutine、異步IO的概念,但都屬於技巧性的內容,講的不透徹就再也不一一分享。
相關文章
相關標籤/搜索