天天看點

Python子產品化程式設計-高階函數#學習猿地

### 遞歸函數

> 遞歸函數就是定義了一個函數,然後在函數内,自己調用了自己這個函數

> 遞歸函數内必須要有結束,不然就會一隻調用下去,直到調用的層數越來越多,棧溢出

> 遞歸函數是一層一層的進入,再一層一層的傳回

##### 初步認識遞歸函數

```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)     

# 疊代器一定是一個可疊代的對象,可疊代對象不一定是疊代器                      

```