lambda表達式
lambda表達式就是能嵌入到其他表達式當中的匿名函數(閉包)
意義:
2、引入了閉包。基本上常見的支持lambda表達式的語言里,不存在不支持閉包的lambda表達式;從函數式編程的角度來說,支持閉包也是很重要的。
創建語法:
lambda parameters:express
parameters:可選,如果提供,通常是逗號分隔的變量表達式形式,即位置參數。
expression:不能包含分支或循環(但允許條件表達式),也不能包含return(或yield)函數。如果為元組,則應用圓括號將其包含起來。
實例(實驗環境為Python3.6)
兩數求和:
#lambda >>>my_lambda = lambda x,y;x+y #執行 >>>result = my_lambda(1,2)
result=3
求n的階乘:
>>>n=5 >>>reduce(lambda x,y:x*y, range(1,n+1) 120
把lambda 作為返回表達式
>>> b=lambda x:lambda y:x+y >>>a=b(3) >>>a(2) 5 >>>(b(2))(2) 4
內建函數:(map,reduce,filter,sorted)
map()函數接收兩個參數,一個是函數,一個是序列,map將傳入的函數依次作用到序列的每個元素,並把結果作為新的list返回
(python3.6)
>>> list(map(lambda x:x*x,[1,2,3,4,5,6,7,8,9])) [1, 4, 9, 16, 25, 36, 49, 64, 81]
reduce()把一個函數作用在一個序列[x1, x2, x3...]上,這個函數必須接收兩個參數,reduce把結果繼續和序列的下一個元素做累積計算,其效果就是:
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
比如上面的求階乘的代碼。
字符串str也是一個序列,我們可以寫一個吧str轉換成int的函數:(python3.6)
>>> def char2num(s): ... return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s] ... >>> from functools import reduce >>> reduce(lambda x,y:x*10+y,map(char2num,'13579')) 13579
filter()函數接收一個函數 f 和一個list,這個函數 f 的作用是對每個元素進行判斷,返回 True或 False,filter()根據判斷結果自動過濾掉不符合條件的元素,返回由符合條件元素組成的新list。
寫一個從list[1,2,3,4,5,6]中刪除偶數,保留奇數的程序(Python3.6)
>>> list(filter(lambda x:x%2==1,[1,2,3,4,5,6])) ... [1, 3, 5]
排序函數 sorted()和list.sort[]
python中,具體到對list進行排序的方法有倆,一個是list自帶的sort方法,這個是直接對list進行操作,只有list才包含的方法;另外一個是內建函數sorted方法,可以對所有可迭代的對象進行排序操作,在本質上,list的排序和內建函數sorted的排序是差不多的,連參數都基本上是一樣的
主要的區別在於,list的sort方法返回的是對已經存在的列表進行操作,而內建函數sorted方法返回的是一個新的list,而不是在原來的基礎上進行的操作。
>>> help(sorted) Help on built-in function sorted in module builtins: sorted(iterable, key=None, reverse=False) Return a new list containing all items from the iterable in ascending order. A custom key function can be supplied to customize the sort order, and the reverse flag can be set to request the result in descending order.
Python3中去除了cmp內置函數,同時sorted等函數也去除了cmp關鍵字,添加key關鍵字
使用sorted()方法和list.sort()方法進行排序 elements=[(2,12,"A"),(1,11,"N"),(1,3,"L"),(2,4,"B")] >>> sorted(elements) [(1, 3, 'L'), (1, 11, 'N'), (2, 4, 'B'), (2, 12, 'A')] 根據elements每個元組后兩項進行排序,e表示列表中每個三元組元素 在表達式是元組,且lambda為一個函數的參數時,lambda表達式的圓括號是必需的 >>> elements.sort(key=lambda e:(e[1],e[2])) >>> elements [(1, 3, 'L'), (2, 4, 'B'), (1, 11, 'N'), (2, 12, 'A')] 分片方式得到同樣的效果 >>> elements.sort(key=lambda e:e[1:3]) >>> elements [(1, 3, 'L'), (2, 4, 'B'), (1, 11, 'N'), (2, 12, 'A')] >>> elements.sort(key=lambda e:(e[2].lower(),e[1])) 以下兩種方法等價,都可以通過調用area(5,3),結果相同 >>> area=lambda b,h:0.5*b*h >>> def area(b,h): return 0.5*b*h
閉包(簡單介紹一下閉包)
在一個內部函數中,對外部作用域的變量進行引用,(並且一般外部函數的返回值為內部函數),那么內部函數就被認為是閉包,舉個栗子(以一個類似棋盤游戲的例子來說明。假設棋盤大小為50*50,左上角為坐標系原點(0,0),我需要一個函數,接收2個參數,分別為方向(direction),步長(step),該函數控制棋子的運動。 這里需要說明的是,每次運動的起點都是上次運動結束的終點。):
>>> origin=[0,0]
>>> def create(pos=origin):
... def go(direction,step):
... new_x=pos[0]+direction[0]*step
... new_y=pos[1]+direction[1]*step
... pos[0]=new_x
... pos[1]=new_y
... return pos
... return go
...
>>> player = create()
>>> print(player([1,0],10))
[10, 0]
>>> print(player([0,1],20))
[10, 20]
>>> print(player([-1,0],10))
[0, 20]
>>>print('player:',player)
function: <function create.<locals>.go at 0x02F94660>
>>> print('function:',go)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'go' is not defined
>>> print('function:',create)
function: <function create at 0x02E4D540>
注意:
- 閉包無法修改外部函數的局部變量
- python循環中不包含域的概念
- 閉包可以保存當前的運行環境
# >>> def outerFunc(): ... x = 0 ... def innerFunc(): ... x = 1 ... print('inner x:',x) ... print('outer x before call inner:',x) ... innerFunc() ... print('outer x after call inner:',x) ... >>> >>> outerFunc() outer x before call inner: 0 inner x: 1 outer x after call inner: 0 >>> #按照正常的理解下面的程序應該輸入0,2,4,對吧? 但實際輸出的是4,4,4,循環在Python中沒有遇到概念,flist在向列表中添加func的時候,並沒有保存i的值而當執行f(2)的時候才去取,這時候循環已經結束,i的值是2,所以結果都是4 >>> flist = []>>> for i in range(3): ... def func(x): ... return x*i ... flist.append(func) ... >>> for f in flist: ... print(f(2)) ... 4 4 4 #修改方案 >>> flist = [] >>> for i in range(3): ... def makefunc(i): ... def func(x): ... return x*i ... return func ... flist.append(makefunc(i)) ... >>> for f in flist: ... print(f(2)) ... 0 2 4 >>> #(f是一個函數 序列) 在func外面再定義一個makefunc函數,func形成閉包