day 12

1. 閉包函數

閉包函數:將 閉包函數內部的變量 與 閉包函數內部的函數 打包在一塊兒,以函數返回值的形式返回出來閉包

def f1():
    def f2():
        print('from f2')
    return f2   # 將 函數 f2 的對象做爲函數 f1 的返回值
f2 = f1()   # 當調用函數 f1 的時候,實際上在調用函數 f2 ,
f2()

因爲局部做用域與全局做用域下相同名字的變量是沒有任何關係的,因此在正常狀況下,咱們是不能直接在外部調用 函數 f2 ,實現打印功能的,運用閉包的思想,能夠實現這種需求。app

2. 裝飾器

裝飾器:給函數增長功能的函數函數

  • 裝飾器自己也是一個函數,只是被用來裝飾被裝飾的函數
  • 使用裝飾器函數時,不改變被裝飾函數的源代碼
  • 使用裝飾器函數時,不改變被裝飾函數的調用方式

2.1 裝飾器模板

# 裝飾器模板
def deco(func):
    def wrapper(*args, **kwargs):
        res = func(*args, **kwargs)
        return res

    return wrapper

2.2 裝飾器語法糖

當一個函數具備裝飾器時時可使用裝飾器語法進行快捷方便的調用code

# 在被裝飾函數正上方,而且是單獨一行寫上:@裝飾器名
@deco
def f1():
    pass

2.3 三層裝飾器

給二層裝飾器函數傳參。對象

# 三層裝飾器
def sanceng(func3)
    def deco(func):
        def wrapper(*args, **kwargs):
            res = func(*args, **kwargs)
            return res

        return wrapper
    return deco

2.4 裝飾器模板推導過程

2.4.1 不帶參數和返回值的裝飾器

# 模板
def deco(func):
    def wrapper():
        func()    
    return wrapper

假設如今有一個函數 f1作用域

import time
def f1():   # 函數對象 f1
    print('from f1')    # 函數功能
    time.sleep(1)
    
f1()    # 調用方式

如何在不改變函數的源代碼及調用方式的前提下,實現計算 f1 功能耗費的時間it

實現方法以下:模板

import time
def f1():   # 函數對象 f1
    '''被裝飾函數'''
    print('from f1')    # 函數功能
    time.sleep(1)
    
# f1()  # 調用方式

def deco(func): # 2. 這裏的 func 其實是真正的 f1 函數對象
    '''裝飾器'''
    def wrapper():  # 3. 添加須要實現的功能
        start = time.time()
        func()      # 4. 至關於 f1(),調用函數 f1
        end = time.time()
        print(end - start)
    return wrapper  # 5. 將實現功能的函數對象 wrapper 和 結果 打包返回給裝飾器函數 deco
f1 = deco(f1)   # 1. 將函數對象 f1 看成參數傳給裝飾器函數,會的到一個返回值對象使用 f1 接收,這裏的 f1只是個普通的變量名,可是接收了函數對象 wrapper
f1() # 6. 實現了 f1 原來的功能,同時獲得了運行程序的時間(這裏的其實是在調用裝飾器函數裏面的 wrapper ,已經不是原來的函數 f1 了)

2.4.2 帶返回值的裝飾器

# 模板
def deco(func):
    def wrapper():
        res = func()    
    return wrapper

假設如今有一個函數 f1class

import time
def f1():   # 函數對象 f1
    print('from f1')    # 函數功能
    time.sleep(1)
    return '返回值'
    
# f1()  # 調用方式

在不改變函數的源代碼及調用方式的前提下,實現計算 f1 功能耗費的時間

實現方法以下:

import time
def f1():   # 函數對象 f1
    '''被裝飾函數'''
    print('from f1')    # 函數功能
    time.sleep(1)
    return '返回值'
    
# f1()  # 調用方式

def deco(func): # 2. 這裏的 func 其實是真正的 f1 函數對象
    '''裝飾器'''
    def wrapper():  # 3. 添加須要實現的功能
        start = time.time()
        res = func()        # 4. 拿到真正 f1 函數的返回值
        end = time.time()
        print(end - start)
        
        return res  # 5. 將 f1 函數的返回值返回給 wrapper
    return wrapper  # 5. 將實現功能的函數對象 wrapper 和 返回值 打包返回給裝飾器函數 deco
f1 = deco(f1)   # 1. 將函數對象 f1 看成參數傳給裝飾器函數,會的到一個返回值對象使用 f1 接收,這裏的 f1只是個普通的變量名,可是接收了函數對象 wrapper
res = f1() # 6. 獲得了 f1 的返回值,同時獲得了運行程序的時間(這裏的其實是在調用裝飾器函數裏面的 wrapper ,已經不是原來的函數 f1 了)

2.4.3 帶參數和返回值的裝飾器

假設如今有一個函數 f1,比較兩個數的大小,一樣的添加計算程序運行的時間

def f1(x, y, z=10):
    '''被裝飾函數'''
    if x > y:
        return x
    else:
        return z


f1(3, 5)  # 結果是 10
f1(5, 3)  # 結果是 5

在不改變函數的源代碼及調用方式的前提下,實現計算 f1 功能耗費的時間

實現方法以下:

def f1(x, y, z=10):
    if x > y:
        time.sleep(1)
        return x
    else:
        time.sleep(2)
        return z


f1(3, 5)  # 結果是 10
f1(5, 3)  # 結果是 5


def deco(func): # 2. 這裏的 func 其實是真正的 f1 函數對象
    '''裝飾器'''
    def wrapper(*args, **kwargs):   # 3. 添加須要實現的功能,使用*args, **kwargs接收全部原函數可能傳進來的值
        start = time.time()
        res = func(*args, **kwargs)     # 4. 使用*args, **kwargs打散全部可能傳進來的參數
        end = time.time()
        print(end - start)
        
        return res  # 5. 將 f1 函數的返回值返回給 wrapper
    return wrapper  # 5. 將實現功能的函數對象 wrapper 和 返回值 打包返回給裝飾器函數 deco
f1 = deco(f1)   # 1. 將函數對象 f1 看成參數傳給裝飾器函數,會的到一個返回值對象使用 f1 接收,這裏的 f1只是個普通的變量名,可是接收了函數對象 wrapper
res = f1(5, 3) # 6. 獲得了 f1 的返回值,同時獲得了運行程序的時間(這裏的其實是在調用裝飾器函數裏面的 wrapper ,已經不是原來的函數 f1 了)
print(res)
相關文章
相關標籤/搜索