函數進階· 第3篇《常用內置函數filter()、map()、zip(),怎麼用的呢?》
堅持原創輸出,點擊藍字關注我吧
作者:清菡
部落格:oschina、雲+社區、知乎等各大平台都有。
由於微信公眾號推送改為了資訊流的形式,防止走丟,請給加個星標
,你就可以第一時間接收到本公眾號的推送!
目錄
- 一、filter()函數
- 1.filter()過濾序列
- 2.生成器、迭代器都是可迭代對象
- 二、map()函數
- 三、zip()函數
- 1.什麼是 zip()函數
- 2.zip()可以快速創建字典
常用的內置函數:
- map()函數:會根據提供的函數對指定序列做映射。
- filter()函數:函數用於過濾序列。
- zip()函數:函數用於將可迭代的對象作為參數,將對象中對應的元素打包成一個個元組。
一、filter()函數
1.filter()過濾序列
filter:過濾序列。第一參數是函數;第二參數是可迭代對象。
看看filter()
這個內置函數的源碼:
class filter(object):
"""
filter(function or None, iterable) --> filter object
Return an iterator yielding those items of iterable for which function(item)
is true. If function is None, return the items that are true.
"""
def __getattribute__(self, *args, **kwargs): # real signature unknown
""" Return getattr(self, name). """
pass
def __init__(self, function_or_None, iterable): # real signature unknown; restored from __doc__
pass
def __iter__(self, *args, **kwargs): # real signature unknown
""" Implement iter(self). """
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
def __next__(self, *args, **kwargs): # real signature unknown
""" Implement next(self). """
pass
def __reduce__(self, *args, **kwargs): # real signature unknown
""" Return state information for pickling. """
pass
看源碼發現居然是個類。
它接收到的是2個參數,2個參數在哪裡看呢?
__init__
方法裡面看。既然是個類,調用的時候創建一個對象。
Python 中的可迭代對象在一個模組裡面。迭代器、生成器、可迭代對象都在這個模組裡面。
from collections import Iterator,Iterable,Generator
生成器屬於迭代器,生成器是可迭代對象。
列表是個可迭代對象。filter()
這個內置函數傳 2 個參數後,會返回出一個對象。
看filter()
源碼可以看出它是個類,調用它給它傳參,類返回的結果肯定是個對象。
filter()
的作用是過濾,它會進行迭代操作。
它會把後面傳入的可迭代對象,裡面的元素全部遍歷一遍。然後把遍歷出來的元素當作參數傳到這個fun
函數裡面。
當前這個fun()
函數沒有定義參數,這個時候運行看看:
# 內置函數
def fun():
pass
li = [1,2,122,331,11,22,33,4,6,7,2,88,31]
res=filter(fun,li)
print(list(res))
返回列表的時候報錯了,fun()
需要 0 個參數,但是這裡給了一個參數:
當我們把它轉換成列表的時候,在這裡傳進去,它會返回一個對象,這個對象里有一個函數,還有個可迭代對象filter(fun,li)
。
使用filter()
傳出來的數據也是個迭代器。它也是個可迭代對象,就可以通過list
把它轉換成列表。
當你轉換的時候,它會把第一個參數拿到,傳到fun()
裡面去,會自動傳參的。
加個參數,再運行:
# 內置函數
def fun(n):
pass
li = [1,2,122,331,11,22,33,4,6,7,2,88,31]
res=filter(fun,li)
print(list(res))
運行結果:
這個列表是空的。因為函數pass
掉了。只寫個pass
,調用這個函數,返回的值是沒有結果的。
filter()
會根據傳進去的參數,調用func()
函數,這個函數根據返回值pass
,來確定函數li
要不要添加到新的列表裡面。
如果將程式碼修改成這樣return True
:
def fun(n):
return True
li = [1,2,122,331,11,22,33,4,6,7,2,88,31]
res=filter(fun,li)
print(list(res))
返回結果:
返回一個 False:
輸出結果是一個都沒有了。
filter()
函數可以過濾,可以寫過濾條件。比如要保留n<10
的數據要保留下來,n<10
是個比較語句。
n<10
返回的是個 True(當前傳入的參數保留,添加到新的列表裡面),n>10
返回的是個 False(就把數據去掉不要了):
def fun(n):
return n<10
li = [1,2,122,331,11,22,33,4,6,7,2,88,31]
res=filter(fun,li)
print(list(res))
其實和這段程式碼的操作是一樣一樣的:
li1 = []
for i in li:
if i > 10:
li1.append(i)
內部操作是這樣的:
定義了個新的列表li1
,在這裡面來了一個for
循環,判斷i
是不是大於 10,如果大於 10,就把它添加到新的列表裡面。
會根據你傳入的參數fun(n)
進行相應的判斷和比較。根據函數返回的是True
還是None
,來決定這個數據要不要保留起來。
2.生成器、迭代器都是可迭代對象
定義個生成器、可迭代對象、迭代器:
from collections import Iterator,Iterable,Generator
def fun(n):
return n < 10
# 列表就是可迭代對象
li = [1, 2, 122, 331, 11, 22, 33, 4, 6, 7, 2, 88, 31]
res = filter(fun, li)
# 定義個迭代器
# 可以把一個可迭代對象轉換成一個迭代器
li2 = iter(li)
# 定義個生成器
li3 = (i for i in range(5))
# 用isinstance 判斷下列表是不是個可迭代對象
print(isinstance(li,Iterable))
print(isinstance(li2,Iterable))
print(isinstance(li3,Iterable))
isinstance()
函數來判斷一個對象是否是一個已知的類型,類似 type()
。
返回都是True
,所以它們 3 個都是可迭代對象。
生成器屬於迭代器,那麼生成器也是可迭代對象。迭代器是可迭代對象,但是迭代器不是生成器。
二、map()函數
map()
的機制和filter()
是一樣的。它也會將後面的可迭代對象裡面的數據迭代出來,放到第一個函數裡面。
它接收的也是 2 個參數。第一個參數:func
,第二個參數:可迭代對象。
def fun(n):
return n < 10
# 列表就是可迭代對象
li = [1, 2, 122, 331, 11, 22, 33, 4, 6, 7, 2, 88, 31]
res = filter(fun, li)
# map:將可迭代對象中的數據迭代出來,一個一個傳到函數中去調用,將返回結果放到新的對象中。
res2=map(fun,li)
print(list(res2))
它返回的結果全是True
和False
。
map()函數可以用來做:
1.把這些數據做統一的處理,比如算這些數據的階乘,有一批數據要算階乘,可以一起拿過去。
2.它會把數據當作個參數,放到函數里去調用。
3.然後把函數的返回值放到一個列表裡面。
它返回什麼就放什麼,改成返回 1000:
改成n*2
:
map()
將可迭代對象裡面的元素迭代出來,每個元素當作一個參數,傳到前面這個函數fun
裡面,然後把函數的返回值添加到新的列表裡面。
要統一處理一批數據的時候,就可以通過它來做。
三、zip()函數
1.什麼是 zip()函數
zip()函數後面接收的是個可迭代對象,後面可接收多個可迭代對象。
來看看 zip 的源碼:
它的內部其實也是個類,那麼它返回的就是個可迭代對象。
準確得來說,它是個迭代器,迭代器也屬於可迭代對象。
例如:
# zip # 打包
res3 = zip([1, 2, 3], [11, 22, 33])
print(res3)
在 Python2 的時候,filter()
、map()
、zip()
函數返回出來的直接是列表。Python3 做了個性能的優化,返回的是個迭代器,可以節約記憶體。
通過next()
去取值,能獲取出來內容的話,說明它就是個迭代器:
直接一次性把它轉換成列表,方便看結果:
# zip # 打包
res3 = zip([1, 2, 3], [11, 22, 33])
print(list(res3))
它是這樣打包的:
使用zip()
函數傳入 2 個可迭代對象,把第一個可迭代對象的第一個元素和第二個可迭代對象的第一個元素拿出來打包成一個元組,後面以此類推。
為什麼裡面放的是元組?
元組省記憶體啊。
如果可迭代對象裡面元素多少不一樣(長短不一)怎麼辦?
# zip # 打包
res3 = zip([1, 2, 3], [11, 22, 33,44,55],[111,222,333],[111,222,333])
print(list(res3))
它會只會保留最短的。
程式碼中最短的一組:這裡只有 3 個元素。
那麼這裡的話,只會分成 3 組。就算第二組有 5 個元素,只會拿第一個、第二個、第三個。多餘的數據清除掉了,不要了。
2.zip()可以快速創建字典
你看,和字典items()
取值出來的數據是一樣的:
通過dict
轉換下,你看,它變成了一個字典:
# zip # 打包
res3 = zip([1, 2, 3], [11, 22, 33])
print(dict(list(res3)))
dict1={"key1":1,"key2":2,"key3":3}
print(list(dict1.items()))
創建字典的時候,可通過這種方式快速創建字典。
把鍵放在一個列表裡,把值放在一個列表裡,通過zip()
打包一下,通過dit()
就能把它轉換成一個字典。
公眾號清菡軟體測試首發,更多原創文章:清菡軟體測試 112+原創文章,歡迎關注、交流,禁止第三方擅自轉載。