內部函數
- 函數裏面 定義的 函數 --> 內部函數
- 內部函數 修改 外部的變量 nonlocal
- 內部函數 修改 全局的變量 global
a = 100
def func():
b = 99
def func_son():
global a
nonlocal b
c = 88
b += 1
a += 1
print(a, b, c)
- globals() # 查看全局變量、函數
- locals() # 查看內部變量、函數
閉包
- 是什麼?
- 函數中 的概念
- 調用 函數的內部函數、內部變量
- 函數返回自己的內部函數名,這就是閉包
return 內部函數名
def func():
def func_son():
a = 10
print(a)
return func_son # 不加(), 返回的是函數,不是調用函數
x = func() # x 即爲 func_son
x() # 給x加() 即 調用 func_son()
閉包的參數、變量
- 閉包的作用域
- 內部函數每次重新加載,但是 內部函數 訪問的仍是同一個外部函數
裝飾器
- 應用廣泛,依賴閉包,是在閉包的基礎上的升級
條件一 函數作爲參數
條件二 閉包的特點
def decrator(func): # 定義一個裝飾器
a = 100
def wrapper(): # 包裝 裝飾
func() # 調用被裝飾函數,保持其原功能
print(' wrapper print a :', a)
return wrapper
decrator(xxx) # 傳入函數名 作爲參數
如何使用裝飾器 @
- 在簡單函數上面 @裝飾器名字
# 使用裝飾器
@decrator
def house():
print('i am 毛坯房')
house()
假如在開發完成後,發現house()函數還有不足,需要豐富一下。
-
更改原函數 – 不可取
- 不一定所有調用原函數都需要更改
-
新增一個函數 – 不可取
- 需要改 原來調用 house()的代碼
裝飾器 在不改變原函數名、原函數體 的情況下,對函數功能進行修改
# 完整
def decrator(func): # 定義一個裝飾器
a = 100
print('wrapper 外層打印 仍然 執行 ')
def wrapper(): # 包裝 裝飾
print(' wrapper print a :', a)
func()
print(' 裝飾器在原函數的基礎上,增加了一個 a:{} 的輸出 '.format(a))
print('即使不調用,由於@decrator,wrapper 外層打印 仍然執行 ')
return wrapper
# 使用裝飾器
@decrator
def house():
print(' house() :i am 毛坯房, 原函數,保持原功能')
# house()
- @decrator 步驟分析
- 將其下方函數,作爲參數 傳給decrator()
- 底層 默執行decrator()函數,裏面的代碼
- 執行到 wrapper(), 加載wrapper內容(未執行)
- 最後 return wrapper
- 默認 同名的house 接收 返回的wrapper
- 打印 wrapper 地址id
- 打印 此時的 新house 地址id
- 下面的新house 即爲 wrapper, 其中調用了原house
帶有參數的 原函數
- wrapper 也傳入同樣參數即可:
def decrator(func): # 定義一個裝飾器
def wrapper(x): # 包裝 裝飾
func(x) # 調用被裝飾函數,保持其原功能
print(' wrapper print a :', a)
return wrapper
萬能 傳入參數
- 可變參數
def decrator(func): # 定義一個裝飾器
def wrapper(*args, **kwargs): # 包裝 裝飾
func(*args, **kwargs) # 調用被裝飾函數,保持其原功能
print(' wrapper print a :', a)
return wrapper
兩層裝飾器
@decrator2
@decrator1
house()
首先 近的decrator1 生效,
然後 decrator2 生效
- 可以分析:
- decrator2 先裝飾完
- decrator1 裝飾 被 decrator2 裝飾過的house
- 調用的是 被 decrator1 裝飾過的 house
- 相當於 func(func1(func2()))
裝飾器 自帶 參數
- 只要裝飾器自帶參數
- 兩層裝飾器!
def decrator_outer(a): # 接收 裝飾器 參數
# 原 裝飾器
def decrator(func): # 接收 函數
def wrapper(*args, **kwargs): # 接收 函數參數
func(*args, **kwargs)
print(a)# 調用被裝飾函數,保持其原功能
return wrapper
# 返回原 裝飾器
return decrator
@decrator_outer(3)