### 遞歸函數
> 遞歸函數就是定義了一個函數,然後在函數内,自己調用了自己這個函數
> 遞歸函數内必須要有結束,不然就會一隻調用下去,直到調用的層數越來越多,棧溢出
> 遞歸函數是一層一層的進入,再一層一層的傳回
##### 初步認識遞歸函數
```python
# 初步認識 遞歸函數 3 2 1 0
def digui(num):
print(num) # 3 2 1 0
# 檢測目前的值是否到了零
if num > 0:
# 調用函數本身
digui(num-1)
print(num) # 0 1 2 3
digui(3)
'''
解析目前遞歸函數的執行過程:
digui(3) ==> 3
digui(3-1) ==> 2
digui(2-1) ==> 1
digui(1-1) ==> 0
digui(0) ==> 0
digui(1) ==> 1
gidui(2) ==>2
digui(3) ==> 3
'''
```
### 回調函數
> 函數中的參數可以是任意類型的,那參數能不能是一個函數呢?
>
> 如果在一個函數中要求傳遞的參數是一個函數作為參數,并且在函數中使用了傳遞進來的函數,那麼這個函數我們就可以稱為是一個回調函數
```python
# 定義一個函數,函數中的一個參數要求是另一個函數
# 帶有回調函數參數的函數
# def func(f):
# print(f,type(f))
# 并且在函數中調用了傳遞進來的行參函數
# f()
# 回調函數
# def love():
# print('123')
#
# func(love)
```
### 閉包函數
> 既然可以把函數作為一個行參進行傳遞,作為回調函數,那麼如果在一個函數中,傳回了一個函數呢?
>
> 在一個函數内傳回了一個内函數, 并且這個傳回的内函數還使用了外函數中局部變量,這就是閉包函數
**特點:**
1. 在外函數中定義了局部變量,并且在内部函數中使用了這個局部變量
2. 在外函數中傳回了内函數,傳回的内函數就是閉包函數
3. 主要在于保護了外函數中的局部變量,既可以被使用,又不會被破壞
4. 檢測一個函數是否為閉包函數,可以使用 `函數名.__closure__ `如果是閉包函數傳回 cell
```python
# 定義一個函數
def person():
money = 0 # 函數中定義了一個局部變量
# 工作 定義的内函數
def work():
nonlocal money # 在内函數中使用了外函數的臨時變量
money += 100
print(money)
# 在外函數中傳回了内函數,這個内函數就是閉包函數
return work
res = person() # return work res = work
res() # res() == work()
res()
res()
res()
# 此時 就不能夠在全局中對money這個局部變量進行任何操作了,
# 閉包的作用:保護了函數中的變量不受外部的影響,但是又能夠不影響使用
```
### 匿名函數 lambda 表達式
> 匿名函數的意思就是說可以不使用def定義,并且這個函數也有沒有名字
>
> 在python中可以使用lambda表達式來定義匿名函數
>
> 注意:lambda表達式僅僅是一個表達式,不是一個代碼塊,是以lambda又稱為一行代碼的函數
>
> lambda表達式也有行參,并且不能通路除了自己的行參之外的任何資料包括全局變量
```python
'''
文法:
lambda [參數清單]:傳回值
'''
# 封裝一個函數做加法運算
# 普通函數
def jia(x,y):
return x+y
# print(jia(2,3))
# 改成lambda表達式來封裝
res = lambda x,y:x+y
# print(res(4,4))
# 帶有分支結構的lambda 表達式
# lambda 參數清單: 真區間 if 表達式判斷 else 假區間
res = lambda sex:"很man" if sex=='男' else "很nice"
print(res('女'))
```
### 疊代器
> 疊代器是python中最具特色的功能之一,是通路集合元素的一種方式
>
> 疊代器是一個可以記住通路周遊的位置的對象
>
> 從集合的第一個元素開始通路,直到集合中的所有元素被通路完畢
>
> 疊代器隻能從前往後一個一個的便利,不能後退
>
> 能被next()函數調用,并不斷傳回下一個值的對象稱為疊代器(Iterator 疊代器對象)
#### iter()
> 功能:把可疊代的對象,轉為一個疊代器對象
> 參數:可疊代的對象 (str,list,tuple,dict
> 傳回值: 疊代器對象
> 注意:疊代器一定是一個可以疊代的對象,但是可疊代對象不一定是疊代器
#### next()
> next()函數可以去調用疊代器,并傳回疊代器中的下一個資料
#### 疊代器的取值方案
1. next() 調用一次擷取一次,直到資料被取完
2. list() 使用list函數直接取出疊代器中的所有資料
3. for 使用for循環周遊疊代器的資料
##### 疊代器取值的特點,取出一個少一個,直到都取完,最後再擷取就會報錯
#### 檢測疊代器和可疊代對象的方法
```python
from collections.abc import Iterator,Iterable
varstr = '123456'
res = iter(varstr)
# type() 函數傳回目前資料的類型,
# isinstance() 檢測一個資料是不是一個指定的類型
r1 = isinstance(varstr,Iterable) # True 可疊代對象
r2 = isinstance(varstr,Iterator) # False 不是一個疊代器
r3 = isinstance(res,Iterable) # True 可疊代對象
r4 = isinstance(res,Iterator) # True 是一個疊代器
print(r1,r2)
print(r3,r4)
# 疊代器一定是一個可疊代的對象,可疊代對象不一定是疊代器
```