深入瞭解和熟練使用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)

at 0x03559E10>

下面我們來看下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)

at 0x03ADE2B8>, at 0x03ADE300>]

>>> flist[0]

at 0x03ADE2B8>

>>> 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 “”, line 1, in

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

一文看懂Python列表表示式及高階函式如lambda方法