一. 解釋下什么是閉包? 有怎樣的場景作用?
- 概念
在函數(shù)嵌套的前提下
內(nèi)層函數(shù)引用了外層函數(shù)的變量(包括參數(shù))
外層函數(shù), 又把 內(nèi)層函數(shù) 當(dāng)做返回值進(jìn)行返回
這個內(nèi)層函數(shù)+所引用的外層變量, 稱為 "閉包" - 標(biāo)準(zhǔn)格式
def test1(a):
b = 10
其他函數(shù)定義代碼
def test2():
print(a)
print(b)
return test2
- 應(yīng)用場景
外層函數(shù), 根據(jù)不同的參數(shù), 來生成不同作用功能的函數(shù) - 案例
根據(jù)配置信息, 生成不同的分割線函數(shù)
def line_config(content, length):
def line():
print("-"*(length // 2) + content + "-"*(length // 2))
return line
line1 = line_config("閉包", 40)
line1()
line2 = line_config("xxxx", 80)
line2()
- 注意事項
- 閉包中, 如果要修改引用的外層變量
需要使用 nonlocal 變量 聲明
否則當(dāng)做是閉包內(nèi), 新定義的變量 - 當(dāng)閉包內(nèi), 引用了一個, 后期會發(fā)生變化的變量時, 一定要注意
函數(shù), 是被調(diào)用時, 才去確定變量標(biāo)識所對應(yīng)的值
- 閉包中, 如果要修改引用的外層變量
二. 簡述對裝飾器的理解
- 作用
在函數(shù)名以及函數(shù)體不改變的前提下, 給一個函數(shù)附加一些額外代碼 - 語法
@裝飾器
def 被裝飾函數(shù)():
code
- 案例
完成基本的 發(fā)說說, 發(fā)圖片 函數(shù)
在上述函數(shù)的基礎(chǔ)上, 嵌入 身份驗證操作, 只有驗證通過后才可以發(fā)說說,發(fā)圖片
def checkLogin(func):
def inner():
print("登錄驗證...")
func()
return inner
# 定義兩個功能函數(shù)
@checkLogin
def fss():
print("發(fā)說說")
# 語法糖 寫法
@checkLogin
def ftp():
print("發(fā)圖片")
# ftp = checkLogin(ftp)
# 相關(guān)的邏輯代碼
btnIndex = 1
if btnIndex == 1:
fss()
else:
ftp()
"開放封閉"原則
已經(jīng)寫好的代碼, 盡可能不要修改
如果想要新增功能, 在原先代碼基礎(chǔ)上, 單獨(dú)進(jìn)行擴(kuò)展
單一職責(zé)
功能保持單一, 不要添加太多的冗余功能
注意
裝飾器的執(zhí)行時間, 是立即執(zhí)行
簡介明了有深度的裝飾器教程鏈接
三. 簡述對生成器的理解?
- 生成器
- 是一個特殊的迭代器(迭代器的抽象層級更高)
- 所以, 擁有迭代器的特性
惰性計算數(shù)據(jù), 節(jié)省內(nèi)存
能夠記錄狀態(tài), 并通過next()函數(shù), 訪問下一個狀態(tài)
具備可迭代特性- 但是, 如果打造一個自己的迭代器, 比較復(fù)雜
需要實現(xiàn)很多方法 后續(xù)在"面向?qū)ο?編程中會進(jìn)行講解
所以, 就有一個更加優(yōu)雅的方式 "生成器"
- 創(chuàng)建方式
- 生成器表達(dá)式
把列表推導(dǎo)式的[] 修改成 ()
(i for i in range(1, 10000000) if i % 2 == 0)- 生成器函數(shù)
函數(shù)中包含 yield語句
這個函數(shù)的執(zhí)行結(jié)果就是 "生成器"
- 產(chǎn)生數(shù)據(jù)的方式
生成器具備可迭代特性
next()函數(shù) 等價于 生成器.next()
for in
- 關(guān)閉生成器
g.close()
后續(xù)如果繼續(xù)調(diào)用, 會拋出StopIteration異常提示
- 注意
如果碰到return
會直接終止, 拋出StopIteration異常提示
生成器只會遍歷一次
四. 什么是遞歸函數(shù)? 有怎樣的應(yīng)用場景?
- 體現(xiàn)
- 函數(shù)A內(nèi)部, 繼續(xù)調(diào)用函數(shù)A
- 概念
傳遞
回歸
- 注意事項
- 有傳遞, 一定要有回歸
- 否則, 就是無限的循環(huán)調(diào)用
- 案例
求一個數(shù)值的階乘
# 9
# 1 * 2 * 3 * ... 9
# 9! = 9 * 8!
# 8 * 7!
# 7 * 6!
# ....
# 1! = 1
# 功能: 如果是不直接知道結(jié)果的數(shù)據(jù), 就進(jìn)行分解 9 9 * 8! 8 =
# 如果說, 直接知道結(jié)果的數(shù)據(jù), 就直接返回 1! = 1
def jiecheng(n):
if n == 1:
return 1
# n != 1
return n * jiecheng(n - 1)
result = jiecheng(5)
print(result)
五. 函數(shù)作用域
- 變量的作用域
變量的作用范圍 , 可操作范圍
- Python是靜態(tài)作用域,也就是說在Python中,變量的作用域源于它在代碼中的位置;
在不同的位置, 可能有不同的命名空間
- 命名空間
- 是作用域的體現(xiàn)形式
- 不同的具體的操作范圍
- Python-LEGB
L-Local
函數(shù)內(nèi)的命名空間
作用范圍: 當(dāng)前整個函數(shù)體范圍
E-Enclosing function locals
外部嵌套函數(shù)的命名空間
作用范圍: 閉包函數(shù)
G-Global
全局命名空間
作用范圍: 當(dāng)前模塊(文件)
B-Builtin
內(nèi)建模塊命名空間
作用范圍: 所有模塊(文件)
注意
Python中沒有塊級作用域
塊級作用域
代碼塊中, 比如 if while for 后的代碼塊
LEGB規(guī)則
按照L -> E -> G -> B 的順序進(jìn)行查找
- 基于命名空間的常見變量類型
- 局部變量
在一個函數(shù)內(nèi)部定義的變量蕴轨;
作用域為函數(shù)內(nèi)部
查看局部變量
locals()- 全局變量
在函數(shù)外部, 文件最外層定義的變量
作用域為整個文件內(nèi)部
查看全局變量
globals()