函式進階· 第3篇《常用內建函式filter()、map()、zip(),怎麼用的呢?》
阿新 • • 發佈:2020-12-25
### 堅持原創輸出,點選藍字關注我吧
![](https://gitee.com/qinghanstudy/qinghan/raw/master/img/20201224165601.png)
作者:清菡
部落格:oschina、雲+社群、知乎等各大平臺都有。
> 由於微信公眾號推送改為了資訊流的形式,防止走丟,請給加個星標 ⭐,你就可以第一時間接收到本公眾號的推送!
# 目錄
- 一、filter()函式
- 1.filter()過濾序列
- 2.生成器、迭代器都是可迭代物件
- 二、map()函式
- 三、zip()函式
- 1.什麼是 zip()函式
- 2.zip()可以快速建立字典
**常用的內建函式:**
- map()函式:會根據提供的函式對指定序列做對映。
- filter()函式:函式用於過濾序列。
- zip()函式:函式用於將可迭代的物件作為引數,將物件中對應的元素打包成一個個元組。
## 一、filter()函式
### 1.filter()過濾序列
**filter:過濾序列。第一引數是函式;第二引數是可迭代物件。**
看看`filter()`這個內建函式的原始碼:
```PYTHON
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__`方法裡面看。既然是個類,呼叫的時候建立一個物件。
![](https://gitee.com/qinghanstudy/qinghan/raw/master/img/20201222135731.png)
Python 中的可迭代物件在一個模組裡面。迭代器、生成器、可迭代物件都在這個模組裡面。
`from collections import Iterator,Iterable,Generator`
生成器屬於迭代器,生成器是可迭代物件。
列表是個可迭代物件。`filter()`這個內建函式傳 2 個引數後,會返回出一個物件。
看`filter()`原始碼可以看出它是個類,呼叫它給它傳參,類返回的結果肯定是個物件。
`filter()`的作用是過濾,它會進行迭代操作。
它會把後面傳入的可迭代物件,裡面的元素全部遍歷一遍。然後把遍歷出來的元素當作引數傳到這個`fun`函式裡面。
當前這個`fun()`函式沒有定義引數,這個時候執行看看:
```PYTHON
# 內建函式
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 個引數,但是這裡給了一個引數:
![](https://gitee.com/qinghanstudy/qinghan/raw/master/img/20201224130742.png)
當我們把它轉換成列表的時候,在這裡傳進去,它會返回一個物件,這個物件裡有一個函式,還有個可迭代物件`filter(fun,li)`。
使用`filter()`傳出來的資料也是個迭代器。它也是個可迭代物件,就可以通過`list`把它轉換成列表。
當你轉換的時候,它會把第一個引數拿到,傳到`fun()`裡面去,會自動傳參的。
![](https://gitee.com/qinghanstudy/qinghan/raw/master/img/20201224131730.png)
加個引數,再執行:
```PYTHON
# 內建函式
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))
```
執行結果:
![](https://gitee.com/qinghanstudy/qinghan/raw/master/img/20201224132059.png)
這個列表是空的。因為函式`pass`掉了。只寫個`pass`,呼叫這個函式,返回的值是沒有結果的。
`filter()`會根據傳進去的引數,呼叫`func()`函式,這個函式根據返回值`pass`,來確定函式`li`要不要新增到新的列表裡面。
如果將程式碼修改成這樣`return True`:
```python
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))
```
返回結果:
![](https://gitee.com/qinghanstudy/qinghan/raw/master/img/20201224133607.png)
返回一個 False:
![](https://gitee.com/qinghanstudy/qinghan/raw/master/img/20201224133723.png)
輸出結果是一個都沒有了。
`filter()`函式可以過濾,可以寫過濾條件。比如要保留`n<10`的資料要保留下來,`n<10`是個比較語句。
`n<10`返回的是個 True(當前傳入的引數保留,新增到新的列表裡面),`n>10`返回的是個 False(就把資料去掉不要了):
```PYTHON
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))
```
![](https://gitee.com/qinghanstudy/qinghan/raw/master/img/20201224134818.png)
其實和這段程式碼的操作是一樣一樣的:
```PYTHON
li1 = []
for i in li:
if i > 10:
li1.append(i)
```
**內部操作是這樣的:**
定義了個新的列表`li1`,在這裡面來了一個`for`迴圈,判斷`i`是不是大於 10,如果大於 10,就把它新增到新的列表裡面。
會根據你傳入的引數`fun(n)`進行相應的判斷和比較。根據函式返回的是`True`還是`None`,來決定這個資料要不要保留起來。
### 2.生成器、迭代器都是可迭代物件
定義個生成器、可迭代物件、迭代器:
```PYTHON
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()`。
![](https://gitee.com/qinghanstudy/qinghan/raw/master/img/20201224143240.png)
返回都是`True`,所以它們 3 個都是可迭代物件。
生成器屬於迭代器,那麼生成器也是可迭代物件。迭代器是可迭代物件,但是迭代器不是生成器。
## 二、map()函式
`map()`的機制和`filter()`是一樣的。它也會將後面的可迭代物件裡面的資料迭代出來,放到第一個函式裡面。
它接收的也是 2 個引數。**第一個引數:`func` ,第二個引數:可迭代物件。**
```PYTHON
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))
```
![](https://gitee.com/qinghanstudy/qinghan/raw/master/img/20201224144608.png)
它返回的結果全是`True`和`False`。
**map()函式可以用來做:**
1.把這些資料做統一的處理,比如算這些資料的階乘,有一批資料要算階乘,可以一起拿過去。
2.它會把資料當作個引數,放到函式裡去呼叫。
3.然後把函式的返回值放到一個列表裡面。
![](https://gitee.com/qinghanstudy/qinghan/raw/master/img/20201224145551.png)
它返回什麼就放什麼,改成返回 1000:
![](https://gitee.com/qinghanstudy/qinghan/raw/master/img/20201224150209.png)
改成`n*2`:
![](https://gitee.com/qinghanstudy/qinghan/raw/master/img/20201224150453.png)
`map()`將可迭代物件裡面的元素迭代出來,每個元素當作一個引數,傳到前面這個函式`fun`裡面,然後把函式的返回值新增到新的列表裡面。
![](https://gitee.com/qinghanstudy/qinghan/raw/master/img/20201224150903.png)
要統一處理一批資料的時候,就可以通過它來做。
## 三、zip()函式
### 1.什麼是 zip()函式
**zip()函式後面接收的是個可迭代物件,後面可接收多個可迭代物件。**
![](https://gitee.com/qinghanstudy/qinghan/raw/master/img/20201224151656.png)
**來看看 zip 的原始碼:**
它的內部其實也是個類,那麼它返回的就是個可迭代物件。
![](https://gitee.com/qinghanstudy/qinghan/raw/master/img/20201224151929.png)
準確得來說,它是個迭代器,迭代器也屬於可迭代物件。
例如:
```PYTHON
# zip # 打包
res3 = zip([1, 2, 3], [11, 22, 33])
print(res3)
```
在 Python2 的時候,`filter()`、`map()`、`zip()`函式返回出來的直接是列表。Python3 做了個性能的優化,返回的是個迭代器,可以節約記憶體。
![](https://gitee.com/qinghanstudy/qinghan/raw/master/img/20201224152817.png)
通過`next()`去取值,能獲取出來內容的話,說明它就是個迭代器:
![](https://gitee.com/qinghanstudy/qinghan/raw/master/img/20201224152948.png)
直接一次性把它轉換成列表,方便看結果:
```PYTHON
# zip # 打包
res3 = zip([1, 2, 3], [11, 22, 33])
print(list(res3))
```
**它是這樣打包的:**
使用`zip()`函式傳入 2 個可迭代物件,把第一個可迭代物件的第一個元素和第二個可迭代物件的第一個元素拿出來打包成一個元組,後面以此類推。
![](https://gitee.com/qinghanstudy/qinghan/raw/master/img/20201224153650.png)
![](https://gitee.com/qinghanstudy/qinghan/raw/master/img/20201224154015.png)
`為什麼裡面放的是元組?`
元組省記憶體啊。
`如果可迭代物件裡面元素多少不一樣(長短不一)怎麼辦?`
```PYTHON
# zip # 打包
res3 = zip([1, 2, 3], [11, 22, 33,44,55],[111,222,333],[111,222,333])
print(list(res3))
```
它會只會保留最短的。
![](https://gitee.com/qinghanstudy/qinghan/raw/master/img/20201224154916.png)
程式碼中最短的一組:這裡只有 3 個元素。
那麼這裡的話,只會分成 3 組。就算第二組有 5 個元素,只會拿第一個、第二個、第三個。多餘的資料清除掉了,不要了。
### 2.zip()可以快速建立字典
你看,和字典`items()`取值出來的資料是一樣的:
![](https://gitee.com/qinghanstudy/qinghan/raw/master/img/20201224161106.png)
通過`dict`轉換下,你看,它變成了一個字典:
```PYTHON
# zip # 打包
res3 = zip([1, 2, 3], [11, 22, 33])
print(dict(list(res3)))
dict1={"key1":1,"key2":2,"key3":3}
print(list(dict1.items()))
```
![](https://gitee.com/qinghanstudy/qinghan/raw/master/img/20201224161248.png)
建立字典的時候,可通過這種方式快速建立字典。
把鍵放在一個列表裡,把值放在一個列表裡,通過`zip()`打包一下,通過`dit()`就能把它轉換成一個字典。
---
公眾號**清菡軟體測試**首發,更多原創文章:**清菡軟體測試 112+原創文章**,歡迎關注、交流,禁止第三方擅自