日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Python 閉包與裝飾器

作者:vincent_duan 更新時間: 2022-09-22 編程語言

函數的作用域

name = "jack"  # 全局作用域

def run():
    name = "rose"  # 局部作用域
    def inner():
        print(name)
    return inner
    
v1 = run()
v1()

v2 = run()
v2()

當執行v1()時,inner()中的name會在自己的作用域中查找,因此namerose
同理,執行v2()時,也會在自己的作用域中查找,因此namerose。
在這里插入圖片描述

閉包

閉包,簡而言之就是將數據封裝在一個包(區域)中,使用時再去里面取。(本質上 閉包是基于函數嵌套搞出來一個中特殊嵌套)
閉包應用場景1:封裝數據防止污染全局。

def func(age):
    name = "jack"

    def f1():
        print(name, age)

    def f2():
        print(name, age)

    def f3():
        print(name, age)

    f1()
    f2()
    f3()

func(20)

閉包應用場景2:封裝數據封到一個包里,使用時在取。

def task(arg):
    def inner():
        print(arg)
    return inner

v1 = task(11)
v2 = task(22)
v3 = task(33)
v1() # 自己的作用域中arg=11
v2() # 自己的作用域中arg=22
v3() # 自己的作用域中arg=33

裝飾器

def outer(origin):
    def inner(*args, **kwargs):
        print("before 110")
        res = origin(*args, **kwargs)  # 調用原來的func函數
        print("after")
        return res

    return inner


@outer  # func1 = outer(func1)
def func1(a1):
    print("我是func1函數")
    value = (11, 22, 33, 44)
    return value


@outer  # func2 = outer(func2)
def func2(a1, a2):
    print("我是func2函數")
    value = (11, 22, 33, 44)
    return value


@outer  # func3 = outer(func3)
def func3(a1):
    print("我是func3函數")
    value = (11, 22, 33, 44)
    return value


func1(1) # 每個函數可以有自己的對應的參數
func2(11, a2=22)
func3(999)

實現原理:基于@語法和函數閉包,將原函數封裝在閉包中,然后將函數賦值為一個新的函數(內層函數),執行函數時再在內層函數中執行閉包中的原函數。

可以在不改變原函數內部代碼 和 調用方式的前提下,實現在函數執行和執行擴展功能。

適用場景:多個函數系統統一在執行前后自定義一些功能。

def outer(origin):
    def inner(*args, **kwargs):
		# 執行前
        res = origin(*args, **kwargs)  # 調用原來的func函數
        # 執行后
        return res
    return inner


@outer
def func():
    pass

func()

functools

上面的裝飾器,一般情況下是沒有問題的。

但是如果有下面的需求,就有可能出現問題:

def handler():
    pass

handler()
print(handler.__name__) # handler
def auth(func):
    def inner(*args, **kwargs):
        return func(*args, **kwargs)
    return inner

@auth
def handler():
    pass

handler()
print(handler.__name__) # inner

可以發現裝飾器實際上就是將原函數更改為其他的函數,然后再此函數中再去調用原函數。

如果我們想獲取函數的函數名,可以使用functools來實現。

import functools


def auth(func):
    @functools.wraps(func)
    def inner(*args, **kwargs):
        """這里是inner的注釋"""
        res = func(*args, **kwargs)  # 執行原函數
        return res

    return inner

原文鏈接:https://blog.csdn.net/vincent_duan/article/details/125888039

欄目分類
最近更新