在知乎上看到的問題——python有哪些優雅的代碼實現。html
下面的代碼大概也算不上優雅。python
一下代碼在python3中實現微信
更多內容可見:http://book.pythontips.com/en/latest/args_and_kwargs.htmlapp
lambda,又稱匿名函數。當咱們在傳入函數時,有些時候,不須要顯式地定義函數,直接傳入匿名函數更方便。函數
好比命名一個普通的函數:spa
def f(x): return x * x
在這裏,f爲函數名,x是函數的參數,x*x則是函數的返回結果。code
咱們能夠換成lambda的形式則是:htm
>>> lambda x : x*x <function <lambda> at 0x7fa2d1298048> >>> f = lambda x : x*x >>> f(3) 9
lambda函數有一個限制就是函數中只能有一個表達式(事例中的x*x),該表達式的結果便是返回值。固然這個表達式能夠用下面的一些技巧寫的更「優雅」一些。對象
其中lambda函數返回是一個對象,其實在python中,絕大部分的都是對象,函數也是對象。因此咱們能將lambda函數賦給其它對象(事例中的f)。可是不建議這麼作。通常使用lambda表達式時要注意:blog
1.邏輯簡單,切忌在一個lambda表達式中作出很複雜的邏輯,這麼作可能感受逼格很高可是代碼的可讀性會變得很是差。
2.一次性使用,就像上面所說的不建議使用f = lambda x:....的形式
map()
函數接收兩個參數,一個是函數,一個是Iterable
,map
將傳入的函數依次做用到序列的每一個元素,並把結果做爲新的Iterator
返回。
好比咱們有一個函數f(x)=x2,要把這個函數做用在一個list [1, 2, 3, 4, 5, 6, 7, 8, 9]
上,就能夠用map()
實現以下:
>>> def f(x): ... return x * x ... >>> r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9]) >>> list(r) [1, 4, 9, 16, 25, 36, 49, 64, 81]
其中注意,傳進map()的第一個參數是 f 而不是f(),其中f表示的是f函數對象自己而f()則是對函數f的調用。
map()
做爲高階函數,事實上它把運算規則抽象了,所以,咱們不但能夠計算簡單的f(x)=x2,還能夠計算任意複雜的函數,好比,把這個list全部數字轉爲字符串:
>>> list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])) ['1', '2', '3', '4', '5', '6', '7', '8', '9']
固然,map()中還能夠傳入lambda表達式:
>>> list(map(lambda x: x*x,range(10))) [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
或者再結合一下:
>>> list(map(lambda x: str(x*x),range(10))) ['0', '1', '4', '9', '16', '25', '36', '49', '64', '81']
再看reduce
的用法。reduce
把一個函數做用在一個序列[x1, x2, x3, ...]
上,這個函數必須接收兩個參數,reduce
把結果繼續和序列的下一個元素作累積計算,其效果就是:
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
比方說對一個序列求和,就能夠用reduce
實現:
>>> from functools import reduce >>> reduce(lambda x,y:x+y,[1,2,3,4]) 10
Python內建的filter()
函數用於過濾序列。
和map()
相似,filter()
也接收一個函數和一個序列。和map()
不一樣的是,filter()
把傳入的函數依次做用於每一個元素,而後根據返回值是True
仍是False
決定保留仍是丟棄該元素。
例如返回一個list中的奇數:
>>> list(filter(lambda x:x % 2 == 1,range(10))) [1, 3, 5, 7, 9]
列表推導,又稱列表生成式,即List Comprehensions,是Python內置的很是簡單卻強大的能夠用來建立list的生成式。
舉個例子,要生成list [0,1, 2, 3, 4, 5, 6, 7, 8, 9]
能夠用list(range(10))
:
>>> list(range(10)) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
在python2中有點區別,python2中的range()直接生產列表而python3中生產的是一個range對象,須要經過list或者[]來生成。
>>> [x for x in range(10)] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
或者進階一點點:
>>> [x*x for x in range(10)] [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] >>> [str(x) for x in range(10)] ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
>>> L = ['Hello', 'World', 'IBM', 'Apple'] >>> [s.lower() for s in L] ['hello', 'world', 'ibm', 'apple']
感受它的寫法有點想lambda表達式。
而後其中也能夠多幾層的嵌套:
>>> [m + n for m in 'ABC' for n in 'XYZ'] ['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']
三層和三層以上的循環就不多用到了。
簡單地講,yield 的做用就是把一個函數變成一個 generator。
例如使用yield生成裴波那契數列:
def fab(max): n, a, b = 0, 0, 1 while n < max: yield b # print b a, b = b, a + b n = n + 1
>>> for n in fab(5): ... print n ... 1 1 2 3 5
使用yield的好處在於,它返回的是一個generator生成器。相似於python3中的range()和python2中的xrange()。帶有 yield 的函數再也不是一個普通函數,Python 解釋器會將其視爲一個 generator,調用 fab(5) 不會執行 fab 函數,而是返回一個 iterable 對象!在 for 循環執行時,每次循環都會執行 fab 函數內部的代碼,執行到 yield b 時,fab 函數就返回一個迭代值,下次迭代時,代碼從 yield b 的下一條語句繼續執行,而函數的本地變量看起來和上次中斷執行前是徹底同樣的,因而函數繼續執行,直到再次遇到 yield。
由於返回的是一個生成器,因此可使用next()方法進行訪問:
>>> f = fab(5) >>> next(f) 1 >>> next(f) 1 >>> next(f) 2 >>> next(f) 3 >>> next(f) 5
generator生成器,前面咱們看了列表推導,使用[]進行生成,其中把[]換成(),就建立了一個generator:
>>> L = [x * x for x in range(10)] >>> L [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] >>> g = (x * x for x in range(10)) >>> g <generator object <genexpr> at 0x7fd2264607d8>
L
是一個list,而g
是一個generator。其中generator是可迭代的。
裝飾器(Decorator),當咱們但願爲函數增長功能,可是卻不想修改原函數又或者沒有權限修改原函數的時候,就須要用到裝飾器了。
好比咱們有一個函數:
def func(): print("I have a dream!") func() I have a dream!
是的,我有一個夢想!如今咱們想要知道我何時有一個夢想,就是咱們須要在執行函數的時候打印時間。那麼:
'''定義一個裝飾器''' def log_time(func): def wrapper(*args, **kw): print("run %s() and time is :" % func.__name__+str(datetime.datetime.now())) return func(*args,**kw) return wrapper @log_time def func(): print("I have a dream!") func()
輸出:
run func() and time is :2016-10-10 14:26:08.296495 I have a dream!
本質上,decorator就是一個返回函數的高階函數。其中,咱們給log_tim()傳入一個參數,這個參數是一個函數對象,而且返回一個函數對象。而後在其中定義了wrapper(),這兩個參數並無意義,只是爲了說明這裏面能夠傳入任意類型的參數。
而後用@語法將其放在函數定義處。其至關於:
func = log_time(func)
因爲log_time()
是一個decorator,返回一個函數,因此,原來的func()
函數仍然存在,只是如今同名的func
變量指向了新的函數,因而調用func()
將執行新函數,即在log_time()
函數中返回的wrapper()
函數。
在使用裝飾器時請注意:
用decorator修飾一個函數獲得另外一個函數時,原來的那個函數依然是邏輯中心,而decorator所增長的只是相對外圍的功能,不能那個什麼賓那個什麼主。
即便去掉裝飾器,整個函數的邏輯仍需完整、清晰。
歡迎多來訪問博客:http://liqiongyu.com/blog
微信公衆號: