一文看懂Python列表表示式及高階函式如lambda方法
深入瞭解和熟練使用python的列表表示式和內建的一些高階函式如lamda, zip, enumerate, map, filter, reduce, sorted方法是python學習,面試和工作的必備技能。正是它們給了python優秀的特性,從而使python有別於其它程式語言。網上的介紹和教程有很多,但感覺還是比較零散,解讀也不夠深入,小編決定再次動手寫篇總結。如果大家還沒讀過小編寫的一文看懂python系列文章,請先閱讀一文看懂Python面向物件程式設計(Python學習與新手入門必看)-絕對原創和一文看懂Python對檔案和資料夾的操作: 含os, shutil和glob模組。Python學習面試必讀。本文內含很多例項程式碼,以幫助新手更好理解。
列表表示式[List Comprehension]
顧名思義,這個表示式作用是以一個快捷的方法對列表進行操作或運算,返回新的
列表
。其使用方式為[表示式 for 變數 in 列表] 或者 [表示式 for 變數 in 列表 if 條件]。
一個最簡單的列表表示式的例子如下。
>>> list1 = [1, 2, 3, 4]
>>> list2 = [ i*i for i in list1]
>>> list3 = [ i*i for i in list1 if i>2]
>>> print(list2)
[1, 4, 9, 16]
>>> print(list3)
[9, 16]
列表表示式也可以遍歷元組生成新的列表(如list5),然而卻不能直接生成新的元組。比如list6實際上是個生成器表示式,不屬於列表表示式了。對於生成器表示式可以透過使用list6。__next__()方法一次一次取值。
>>> tuple1 = (1, 2, 3, 4)
>>> list5 = [ i*i for i in tuple1 ]
>>> print(list5)
[1, 4, 9, 16]
>>> list6 = ( i*i for i in tuple1 )
>>> print(list6)
下面我們來看下3個常考的關於列表表示式應用的例子。
1。統計字串列表中每個字串的長度
>>> words = [‘abc’,‘defg’,‘I love python’, ‘Django’]
>>> len_list = [ len(word) for word in words ]
>>> print(len_list)
[3, 4, 13, 6]
2。 利於列表表示式求兩個列表的交集。
>>> a = [ 3, 5, 6, 8]
>>> b = [ 5, 6]
>>> a_b = [ i for i in a if i in b]
>>> print(a_b)
[5, 6]
3。 打印出100以內所有十位數比個位數大1位的數字。
>>> num = [ n1*10+n2 for n1 in range(0, 10)
for n2 in range(0, 10) if n1 == n2+1 ]
>>> print(num)
[10, 21, 32, 43, 54, 65, 76, 87, 98]
匿名函式lambda函式
Lambda函式又稱匿名函式,也有人稱為lambda表示式。顧名思義,匿名函式就是沒有名字的函式。函式沒有名字也行?當然可以啦。有些函式如果只是臨時一用,而且它的業務邏輯也很簡單時,就沒必要非給它取個名字不可。
lambda匿名函式的格式是 lambda 引數: 表示式。冒號前是引數,可以有多個,用逗號隔開,冒號右邊的為表示式。其實lambda返回值是一個函式的地址,也就是函式物件。下面是個最簡單的lambda函式的例子。
>>> add = lambda x, y: x+y
>>> type(add)
>>> print(add(3,5))
8
既然是匿名函式,我們為什麼還要給它取個叫add的名字?這的確是多次一舉。其實lambda最常用的還是和sorted, map、reduce、filter這些高階函式結合使用。我們再來看下2個使用lambda函式結合sorted方法排序的經典例子。一個按絕對值大小排序,一個按字串長度排序。
>>> list1 = [ 5, -3, 1, 8, -4 ]
>>> list2 = sorted(list1, key=lambda x:abs(x))
>>> print(list2)
[1, -3, -4, 5, 8]
>>> list3 = [ ‘to’, ‘python’, ‘ABC’ ]
>>> list4 = sorted(list3, key=lambda x:len(x))
>>> print(list4)
[‘to’, ‘ABC’, ‘python’]
下面是一道關於lambda函式的經典面試題。flist[0]能輸出什麼?這個主要考函式物件列表,千萬不要和列表表示式搞混了啊。答: flist[0]輸出的是函式物件。
>>> flist = [ lambda x:x*x for x in range(1, 3)]
>>> print(flist)
[
>>> flist[0]
>>> flist[0](2)
4
zip函式
zip()函式來可以把2個或多個列表合併,並建立一個元組對的列表。元組對的數量以合併列表的最短長度為準。python 3中zip方法合併列表後生成的是zip物件,使用list方法可以將其變成列表,使用dict方法可以將其變成字典。
>>> l1 = [ 1, 2, 3 ]
>>> l2 = [ ‘x’, ‘y’, ‘z’]
>>> l3 = [ ‘x’, ‘y’ ]
>>> zip(l1, l2)
>>> print(list(zip(l1, l2)))
[(1, ‘x’), (2, ‘y’), (3, ‘z’)]
>>> print(list(zip(l1, l3)))
[(1, ‘x’), (2, ‘y’)]
>>> print(dict(zip(l1,l3)))
{1: ‘x’, 2: ‘y’}
實際上zip方法支援所有可迭代物件(字串、列表、元祖、字典), 而不僅僅是列表。利用這個特性,我們可以很容易建立各種字典,包括很複雜的字典。我們來看下面2個經典例子。注意zip物件支援直接遍歷哦,不需要先轉成list或dict哦。
>> > l1 = [1, 2, 3]
>> > str1 = “abc”
>> > print(dict(zip(l1, str1)))
{1: ‘a’, 2: ‘b’, 3: ‘c’}
>> > name = [“John”, “Jim”, “Lucy”]
>> > year = [1983, 1985, 1995]
>> > birth_year = dict(zip(name, year))
>> > print(birth_year)
{‘John’: 1983, ‘Jim’: 1985, ‘Lucy’: 1995}
>> > for name, year in zip(name, year):
print(“{} - {}”。format(name, year))
John - 1983
Jim - 1985
Lucy - 1995
利用zip(*some_list)方法可以實現元組列表的反向解壓,見下面案例。注意unzip只支援元組列表,不支援dict直接解壓哦。這也是面試常考內容。
>>> l1 = [(“John”, 1995), (“Lucy”, 2000), (“Max”, 1985)]
>>> name, year = zip(*l1)
>>> print(name)
(‘John’, ‘Lucy’, ‘Max’)
>>> print(year)
(1995, 2000, 1985)
>>> l2 = dict(l1)
>>> print(l2)
{‘John’: 1995, ‘Lucy’: 2000, ‘Max’: 1985}
>>> name1, year1 = zip(*l2)
Traceback (most recent call last):
File “
name1, year1 = zip(*l2)
ValueError: too many values to unpack (expected 2)
enumerate() 函式
enumerate() 函式用於將一個可遍歷的資料物件(如列表、元組或字串)組合為一個索引序列,同時列出資料和資料下標,常見用於for迴圈。一般只有需要同時用到索引index和value值的時候才用enumerate方法。注意直接使用enumerate方法生成是個enumerate物件,可以遍歷的。
>> > name = [“John”, “Lucy”, “Mary”]
>> > name1 = enumerate(name)
>> > print(name1)
< enumerate object at 0x030D0FA8 >
>> > for index, name in enumerate(name):
print(“{}-{}”。format(index, name))
0 - John
1 - Lucy
2 - Mary
map函式
map函式是個非常有用的方法,其語法是 map(function, iterable, 。。。)。map方法可以接收函式作為引數,並將其對映於列表的多個元素。python 2中返回列表,python 3中返回迭代器,需要使用list方法再生成列表。map函式不僅支援自定義的函式和lambda函式,還支援python自帶的函式。
下面是map函式應用一個最簡單的例子。該例子將計算平方的lambda函式對映於列表中的每個元素。
>>> l = map(lambda x: x ** 2, [1, 2, 3, 4, 5])
>>> print(l)
>>> print(list(l))
[1, 4, 9, 16, 25]
map函式還支援多個列表的對映和計算,如下所示。lambda函式中的x, y, z分別對應列表l1, l2和l3中的元素。計算後的生成的列表長度取決於各個列表的最短長度。
>>> l1 = [1, 2, 3]
>>> l2 = [4, 5, 6, 7]
>>> l3 = [8, 9]
>>> print(list(map(lambda x,y,z:x+y+z, l1, l2, l3)))
[13, 16]
我們下面來看下一道關於map函式的經典考題。我們有兩個字串A和B,現在要統計字串A中有多少個字元也在字串B中可以找到。常規函式解法如下:
>>> strA = “aAAAbBCC”
>>> strB = “aA”
>>> def count1(str1, str2):
a = 0
for c in str1:
if c in str2:
a += 1
return a
>>> count1(strA, strB)
4
使用map函式經典解法如下,是不是好簡單好牛叉的樣子?
>>> strA = “aAAAbBCC”
>>> strB = “aA”
>>> print(sum(map(strA。count, strB)))
4
我們現在來分析下上面這段程式碼。python自帶的string。count(char)函式的作用是統計一個字串string含有字元char的數量。在本例中strB相當於char的一個引數列表[“a”, “A”], map函式先統計strA中字元a的數量,再統計strA中字元A的數量,獲得列表[1, 3], 然後將它們相加,即可獲得字串A中總共有多少字元可以在B中找到。
reduce函式
reduce()
函式會對引數序列中元素進行累積。該方法第一個引數必需是函式,而且傳入的函式必需要有2個引數,否則出現錯誤。該方法將一個數據集合(列表,元組等)中的所有資料進行下列操作:用傳給 reduce 中的函式 function先對集合中的第 1、2 個元素進行操作,得到的結果再與第三個資料用 function 函式運算,最後得到一個結果。
reduce函式很適合連續計算(比如列表求和或連乘計算階乘),經典程式碼如下。
>>> from functools import reduce
>>> reduce(lambda x, y: x+y, [1,2,3,4,5])
15
>>> reduce(lambda x,y:x*y,range(1,5))
24
注意: python 3中reduce() 函式已經被從全域性名字空間裡移除了,它現在被放置在 fucntools 模組裡,如果想要使用它,則需要透過引入 functools 模組來呼叫 reduce() 函式。
filter函式
Python的 filter() 函式用於過濾序列,過濾掉不符合條件的元素,返回由符合條件元素組成的新列表。該方法與map和reduce類似,第一個引數都是函式,作用於可以迭代的物件比如列表和元組,但不同的是filter方法傳入的函式是判斷性函式, 只有符合條件的列表元素才會加入新的列表。Python 2中返回列表,python 3中返回filter物件,使用list方法可以轉化為列表。
下面是使用filter方法打印出10以內偶數的經典程式碼。只有滿足x % 2 == 0 的列表元素才會加入新的列表。
>>> l = filter(lambda x: x % 2 == 0, range(10))
>>> print(l)
>>> print(list(l))
[0, 2, 4, 6, 8]
下面這段程式碼利用filter方法刪除字串列表裡的空白字串。只有滿足s and s。strip() = True的字串才會加入新的列表。
def not_empty(s):
return s and s。strip()
list(filter(not_empty, [‘A’, ‘’, ‘B’, None, ‘C’, ‘ ’]))
# 結果: [‘A’, ‘B’, ‘C’]
最好一道是關於filter方法的經典面試題,利用filter方法篩選出一個列表中的素數。網上大多數程式碼都不完美,一是不能對小於等於2的數(包括0, 1和2)做出準確判斷,二是使用了for i in range(2, n+1),做了很多無效迴圈。
>>> import math
>>> def isPrime(n):
if n <= 1:
return False
elif n == 2:
return True
else:
for i in range(2, int(math。sqrt(n))+1):
if n%i == 0:
return False
return True
>>> l1 = [-1, 0, 2, 3, 6, 7, 8]
>>> l2 = list(filter(isPrime, l1))
>>> print(l2)
[2, 3, 7]
小結
本文詳細總結了python的列表表示式及常用高階函式如lambda, zip, map, enumerate, reduce, filter的用法。你學了嗎?看懂的點個贊,沒看懂的留個言啊。如果覺得特別讚的,行個賞啊。接下來本部落格會分3個系列連載,分別為Django系列,一文看懂Python基礎系列和Python爬蟲系列,歡迎關注。
大江狗
2018。8。27