1. 程式人生 > >撩課-Python面試寶典-第八篇

撩課-Python面試寶典-第八篇

一. 解釋下什麼是閉包? 有怎樣的場景作用?

  1. 概念
    在函式巢狀的前提下
    內層函式引用了外層函式的變數(包括引數)
    外層函式, 又把 內層函式 當做返回值進行返回
    這個內層函式+所引用的外層變數, 稱為 “閉包”
  2. 標準格式
	def test1(a):
		b = 10
		其他函式定義程式碼
		def test2():
			print(a)
			print(b)
		return test2
  1. 應用場景
    外層函式, 根據不同的引數, 來生成不同作用功能的函式
  2. 案例
    根據配置資訊, 生成不同的分割線函式
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()
  1. 注意事項
    • 閉包中, 如果要修改引用的外層變數
      需要使用 nonlocal 變數 宣告
      否則當做是閉包內, 新定義的變數
    • 當閉包內, 引用了一個, 後期會發生變化的變數時, 一定要注意
      函式, 是被呼叫時, 才去確定變數標識所對應的值

二. 簡述對裝飾器的理解

  1. 作用
    在函式名以及函式體不改變的前提下, 給一個函式附加一些額外程式碼
  2. 語法
@裝飾器
def 被裝飾函式():
	code
  1. 案例

完成基本的 發說說, 發圖片 函式
在上述函式的基礎上, 嵌入 身份驗證操作, 只有驗證通過後才可以發說說,發圖片


def checkLogin(func):
    def inner():
        print("登入驗證...")
        func()
    return inner

# 定義兩個功能函式
@checkLogin
def fss():
    print("發說說")


# 語法糖 寫法
@checkLogin
def ftp():
    print("發圖片")
# ftp = checkLogin(ftp)


# 相關的邏輯程式碼
btnIndex = 1
if btnIndex == 1:
    fss()
else:
    ftp()

"開放封閉"原則
已經寫好的程式碼, 儘可能不要修改
如果想要新增功能, 在原先程式碼基礎上, 單獨進行擴充套件
單一職責
功能保持單一, 不要新增太多的冗餘功能
注意
裝飾器的執行時間, 是立即執行
簡介明瞭有深度的裝飾器教程連結

三. 簡述對生成器的理解?

  1. 生成器
  • 是一個特殊的迭代器(迭代器的抽象層級更高)
  • 所以, 擁有迭代器的特性
    惰性計算資料, 節省記憶體
    能夠記錄狀態, 並通過next()函式, 訪問下一個狀態
    具備可迭代特性
  • 但是, 如果打造一個自己的迭代器, 比較複雜
    需要實現很多方法 後續在"面向物件"程式設計中會進行講解
    所以, 就有一個更加優雅的方式 “生成器”
  1. 建立方式
  • 生成器表示式
    把列表推導式的[] 修改成 ()
    (i for i in range(1, 10000000) if i % 2 == 0)
  • 生成器函式
    函式中包含 yield語句
    這個函式的執行結果就是 “生成器”
  1. 產生資料的方式
    生成器具備可迭代特性
    next()函式 等價於 生成器.next()
    for in
  1. 關閉生成器
    g.close()
    後續如果繼續呼叫, 會丟擲StopIteration異常提示
  1. 注意
    如果碰到return
    會直接終止, 丟擲StopIteration異常提示
    生成器只會遍歷一次

四. 什麼是遞迴函式? 有怎樣的應用場景?

  1. 體現
    • 函式A內部, 繼續呼叫函式A
    • 概念
      傳遞
      迴歸
  2. 注意事項
    • 有傳遞, 一定要有迴歸
    • 否則, 就是無限的迴圈呼叫
  3. 案例
    求一個數值的階乘
# 9
# 1 * 2 * 3 * ... 9



# 9! = 9 * 8!
#         8 * 7!
#             7 * 6!
#                ....
#                  1! = 1

# 功能: 如果是不直接知道結果的資料, 就進行分解 9 9 * 8! 8 =
# 如果說, 直接知道結果的資料, 就直接返回 1! = 1
def jiecheng(n):
    if n == 1:
        return 1
    # n != 1
    return n * jiecheng(n - 1)

result = jiecheng(5)
print(result)

五. 函式作用域

  1. 變數的作用域
    變數的作用範圍 , 可操作範圍
  1. Python是靜態作用域,也就是說在Python中,變數的作用域源於它在程式碼中的位置;
    在不同的位置, 可能有不同的名稱空間
  1. 名稱空間
  • 是作用域的體現形式
  • 不同的具體的操作範圍
  • Python-LEGB
    L-Local
    函式內的名稱空間
    作用範圍: 當前整個函式體範圍
    E-Enclosing function locals
    外部巢狀函式的名稱空間
    作用範圍: 閉包函式
    G-Global
    全域性名稱空間
    作用範圍: 當前模組(檔案)
    B-Builtin
    內建模組名稱空間
    作用範圍: 所有模組(檔案)
    注意
    Python中沒有塊級作用域
    塊級作用域
    程式碼塊中, 比如 if while for 後的程式碼塊
    LEGB規則
    按照L -> E -> G -> B 的順序進行查詢
  1. 基於名稱空間的常見變數型別
  • 區域性變數
    在一個函式內部定義的變數;
    作用域為函式內部
    檢視區域性變數
    locals()
  • 全域性變數
    在函式外部, 檔案最外層定義的變數
    作用域為整個檔案內部
    檢視全域性變數
    globals()