最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python 函數(shù)裝飾器應(yīng)用教程

 更新時(shí)間:2021年12月02日 09:46:24   作者:無(wú)風(fēng)聽(tīng)海  
函數(shù)裝飾器是Python提供的一種增強(qiáng)函數(shù)功能的標(biāo)記函數(shù),本文將帶大家深入學(xué)習(xí)一下Python 函數(shù)裝飾器,感興趣的同學(xué)跟隨小編一起學(xué)習(xí)吧

一、什么是函數(shù)裝飾器

1.函數(shù)裝飾器是Python提供的一種增強(qiáng)函數(shù)功能的標(biāo)記函數(shù);

2.裝飾器是可調(diào)用的函數(shù)對(duì)象,其參數(shù)是另一個(gè)函數(shù)(被裝飾的函數(shù));

我們可以使用修飾器來(lái)封裝某個(gè)函數(shù),從而讓程序在執(zhí)行這個(gè)函數(shù)之前與執(zhí)行完這個(gè)函數(shù)之后,分別運(yùn)行某些代碼。這意味著,調(diào)用者傳給函數(shù)的參數(shù)值、函數(shù)返回給調(diào)用者的值,以及函數(shù)拋出的異常,都可以由修飾器訪問(wèn)并修改。這是個(gè)很有用的機(jī)制,能夠確保用戶以正確的方式使用函數(shù),也能夠用來(lái)調(diào)試程序或?qū)崿F(xiàn)函數(shù)注冊(cè)功能,此外還有許多用途。

二、函數(shù)裝飾器的執(zhí)行時(shí)機(jī)

函數(shù)裝飾器在被裝飾函數(shù)編譯解析之后直接執(zhí)行,裝飾器是按照從上到下執(zhí)行的;

函數(shù)裝飾器內(nèi)部定義的返回函數(shù)依附在裝飾器的執(zhí)行環(huán)境中;

函數(shù)裝飾器每次執(zhí)行都會(huì)生成新的返回函數(shù);

import sys

def dec1(m):
    print(f'{sys._getframe().f_code.co_name} is execute, arg {m.__name__}')
    def newm1():
        print(f'{sys._getframe().f_code.co_name}')

    return newm1;

@dec1
def m1():
    print(f'{sys._getframe().f_code.co_name}')

@dec1
def m11():
    print(f'{sys._getframe().f_code.co_name}')

if __name__ == '__main__':
    print(m1)
    print(m11)
    print(f'm1==m11:{m1==m11}')
    
# dec1 is execute, arg m1
# dec1 is execute, arg m11
# <function dec1.<locals>.newm1 at 0x7fdfa97d9160>
# <function dec1.<locals>.newm1 at 0x7fdfa97d91f0>
# m1==m11:False

三、變量作用域

Python中將變量聲明和賦值操作合一,很容易導(dǎo)致函數(shù)局部變量覆蓋函數(shù)外的變量

b=6
def f():
    print(b)

f()

# 6
b=6
def f():
    print(b)
    b = 9

f()

# UnboundLocalError: local variable 'b' referenced before assignment

通過(guò)生成的字節(jié)碼可以看到兩者對(duì)變量b的處理的差異,前者直接LOAD_GLOBAL,后者是LOAD_FAST,但是給b賦值卻在print之后導(dǎo)致報(bào)錯(cuò);

from dis import dis

b=6
def f():
    print(b)
    # b = 9

dis(f)

 # 5           0 LOAD_GLOBAL              0 (print)
 #              2 LOAD_GLOBAL              1 (b)
 #              4 CALL_FUNCTION            1
 #              6 POP_TOP
 #              8 LOAD_CONST               0 (None)
 #             10 RETURN_VALUE
from dis import dis

b=6
def f():
    print(b)
    b = 9
    
#  5          0 LOAD_GLOBAL              0 (print)
#             2 LOAD_FAST                0 (b)
#             4 CALL_FUNCTION            1
#             6 POP_TOP

#  6          8 LOAD_CONST               1 (9)
#             10 STORE_FAST               0 (b)
#             12 LOAD_CONST               0 (None)
#             14 RETURN_VALUE

可以使用global來(lái)強(qiáng)制聲明b是全局變量,然后就可以重新賦值了;

b=6
def f():
    global b
    print(b)
    b = 9

f()

# 6

四、閉包

閉包是是指可以訪問(wèn)非在函數(shù)體內(nèi)定義的非全局變量的函數(shù);

通過(guò)函數(shù)的__code__及__closure__可以看到局部變量和自由變量及閉包的情況;

def makesum():
    sum = [0]

    def s(val):
        sum[0] += val
        return sum[0]

    return s



s = makesum()
print(s(1))
print(s(2))
print(s.__code__.co_varnames)
print(s.__code__.co_freevars)
print(s.__closure__)
print(s.__closure__[0].cell_contents)


# 1
# 3
# ('val',)
# ('sum',)
# (<cell at 0x7f63321f1b20: list object at 0x7f63321e8a00>,)
# [3]

基于三中Python變量作用域的緣故,上邊的sum只能使用列表對(duì)象,python提供的nonlocal關(guān)鍵字可以直接使用int類型的變量;

def makesum():
    sum = 0

    def s(val):
        nonlocal sum
        sum += val
        return sum

    return s

s = makesum()
print(s(1))
print(s(2))
print(s.__code__.co_varnames)
print(s.__code__.co_freevars)
print(s.__closure__)
print(s.__closure__[0].cell_contents)


# 1
# 3
# ('val',)
# ('sum',)
# (<cell at 0x7f73e6a4ab20: int object at 0x7f73e6b47970>,)
# 3

五、保留函數(shù)的元數(shù)據(jù)

函數(shù)裝飾器默認(rèn)會(huì)使用返回的函數(shù)完全取代被裝飾的函數(shù),這樣可能會(huì)導(dǎo)致序列化或者開(kāi)發(fā)工具智能提示的問(wèn)題;可以使用functools.wraps來(lái)保留原始函數(shù)的標(biāo)準(zhǔn)屬性(name、module、__annotations__等);

import functools

def dec(func):
    def real():
        '''this is real function'''
        pass
    return real

def wrapsdec(func):
    @functools.wraps(func)
    def real():
        '''this is real function'''
        pass
    return real

@dec
def max(nums):
    '''this is max function'''
    pass

@wrapsdec
def sum(nums):
    '''this is sum function'''

print(max)
print(max.__name__)
print(max.__doc__)
print(help(max))
print()
print(sum)
print(sum.__name__)
print(sum.__doc__)
print(help(sum))


# <function dec.<locals>.real at 0x7f1bfd4241f0>
# real
# this is real function
# Help on function real in module __main__:
# 
# real()
#     this is real function
# 
# None
# 
# <function sum at 0x7f1bfd424280>
# sum
# this is sum function
# Help on function sum in module __main__:
# 
# sum(nums)
#     this is sum function
# 
# None

六、支持關(guān)鍵字參數(shù)、位置參數(shù)

def dec(func):
    def real(*args, **kwargs):
        result = func(*args, **kwargs)
        return result

    return real

@dec
def sum(*nums, **kwargs):
    s = 0
    for n in nums:
        s = s + n

    for a in kwargs.values():
        s = s + a
    return s

print(sum(1,2,3,first=1))

七、使用lru_cache緩存函數(shù)執(zhí)行結(jié)果

lru_cache內(nèi)部使用函數(shù)的參數(shù)作為key,使用dict進(jìn)行緩存執(zhí)行結(jié)果,減少重復(fù)計(jì)算;

默認(rèn)支持緩存128條記錄,超過(guò)后采用LRU方式丟棄多余記錄;

需要注意執(zhí)行中不要改變參數(shù),否則會(huì)影響字典key的有效性;

from functools import lru_cache

@lru_cache()
def fibonacci(n):
    print(f'fibonacci({n})')
    if n<2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(6))

# fibonacci(6)
# fibonacci(5)
# fibonacci(4)
# fibonacci(3)
# fibonacci(2)
# fibonacci(1)
# fibonacci(0)
# 8

八、使用singledispatch實(shí)現(xiàn)泛型函數(shù)

python不支持方法或者函數(shù)的重載,我們無(wú)法單獨(dú)定義不同參數(shù)類型的同名函數(shù);

singledispatch提供了這樣一種能力,其通過(guò)注冊(cè)具體的參數(shù)類型和關(guān)聯(lián)的函數(shù);

我們可以在自己的模塊定義自己的類型,并實(shí)現(xiàn)自己的自定義函數(shù);

import math
import numbers
from functools import singledispatch



@singledispatch
def absall(obj):
    return abs(obj)

@absall.register(numbers.Number)
def numabs(num):
    return abs(num)

@absall.register(numbers.Complex)
def cabs(c):
    return math.sqrt(c.real*c.real + c.imag* c.imag)

class Line:

    def __init__(self, startx, starty, endx, endy):
        self.startx = startx
        self.starty = starty
        self.endx = endx
        self.endy = endy

@absall.register(Line)
def lineabs(line):
    y =line.endy - line.starty
    x = line.endx - line.startx
    return math.sqrt(x*x + y*y)

print(absall(-1.1))
print(absall(3+4j))

l = Line(1,2,4,6)
print(absall(l))

# 1.1
# 5.0
# 5.0

九、通過(guò)參數(shù)控制函數(shù)裝飾器的行為

函數(shù)裝飾器本身不支持傳遞參數(shù),解析源代碼的時(shí)候,python會(huì)將被裝飾的函數(shù)對(duì)象作為第一個(gè)參數(shù)傳遞給裝飾器;

我們可以通過(guò)在函數(shù)裝飾器外再嵌套一個(gè)函數(shù)工廠來(lái)承載裝飾特定函數(shù)的時(shí)候設(shè)置的參數(shù);?

def accesscontrol(checkuser=True, updatesession=True):

    def dec(func):
        def checkuserf():
            print('check user')
            return True

        def updatesessionf():
            print('update session')
            return True

        def access():
            if checkuser:
                checkuserf()

            if updatesession:
               updatesessionf()

            func()

        return access

    return dec

@accesscontrol()
def pushitem():
    print('pushitem')
    return True

@accesscontrol(checkuser=False)
def getitem():
    print('getitem')
    return True

# pushitem()
# print()
# getitem()
# 
# check user
# update session
# pushitem
# 
# update session
# getitem

以上就是Python 函數(shù)裝飾器應(yīng)用教程的詳細(xì)內(nèi)容,更多關(guān)于Python 函數(shù)裝飾器的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • python繪制餅圖的方法詳解

    python繪制餅圖的方法詳解

    這篇文章主要為大家詳細(xì)介紹了python繪制餅圖的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-03-03
  • Python爬蟲(chóng)之爬取最新更新的小說(shuō)網(wǎng)站

    Python爬蟲(chóng)之爬取最新更新的小說(shuō)網(wǎng)站

    這篇文章主要介紹了Python爬蟲(chóng)之爬取最新更新的小說(shuō)網(wǎng)站,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)python爬蟲(chóng)的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-05-05
  • Python中使用絕佳的八個(gè)Debug?工具

    Python中使用絕佳的八個(gè)Debug?工具

    在Python開(kāi)發(fā)中,調(diào)試是解決問(wèn)題和提高代碼質(zhì)量的關(guān)鍵,有許多強(qiáng)大的調(diào)試工具可幫助開(kāi)發(fā)者更快速地發(fā)現(xiàn)和解決問(wèn)題,本文將介紹8個(gè)出色的Python調(diào)試工具,并提供詳細(xì)的示例代碼,讓你更好地了解它們的用法和優(yōu)勢(shì)
    2024-01-01
  • Python FTP兩個(gè)文件夾間的同步實(shí)例代碼

    Python FTP兩個(gè)文件夾間的同步實(shí)例代碼

    本文通過(guò)實(shí)例代碼給大家介紹了python ftp兩個(gè)文件夾間的同步,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2018-05-05
  • 淺析Python中yield關(guān)鍵詞的作用與用法

    淺析Python中yield關(guān)鍵詞的作用與用法

    Python中關(guān)鍵字yield的作用是什么?用來(lái)干什么的?這篇文章就給大家詳細(xì)介紹了Python中yield關(guān)鍵詞的作用與用法,文中通過(guò)示例代碼介紹的很詳細(xì),對(duì)大家學(xué)習(xí)python具有一定的參考借鑒價(jià)值,有需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2016-11-11
  • python獲取Pandas列名的幾種方法

    python獲取Pandas列名的幾種方法

    這篇文章主要介紹了python獲取Pandas列名的幾種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • Tensorflow Summary用法學(xué)習(xí)筆記

    Tensorflow Summary用法學(xué)習(xí)筆記

    這篇文章主要介紹了Tensorflow Summary用法學(xué)習(xí)筆記,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • Python之關(guān)于類變量的兩種賦值區(qū)別詳解

    Python之關(guān)于類變量的兩種賦值區(qū)別詳解

    這篇文章主要介紹了Python之關(guān)于類變量的兩種賦值區(qū)別詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-03-03
  • python通過(guò)正則查找微博@(at)用戶的方法

    python通過(guò)正則查找微博@(at)用戶的方法

    這篇文章主要介紹了python通過(guò)正則查找微博@(at)用戶的方法,涉及Python正則匹配的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-03-03
  • python打包生成的exe文件運(yùn)行時(shí)提示缺少模塊的解決方法

    python打包生成的exe文件運(yùn)行時(shí)提示缺少模塊的解決方法

    今天小編就為大家分享一篇python打包生成的exe文件運(yùn)行時(shí)提示缺少模塊的解決方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-10-10

最新評(píng)論

石阡县| 梓潼县| 南和县| 澳门| 凌源市| 白河县| 琼结县| 玉龙| 临夏市| 永胜县| 武隆县| 怀远县| 克什克腾旗| 南岸区| 平和县| 宁国市| 泽州县| 习水县| 林口县| 伊宁市| 敦化市| 广州市| 石景山区| 邢台市| 罗源县| 北流市| 庆城县| 永昌县| 九龙坡区| 恭城| 阿拉善盟| 红原县| 丹巴县| 上栗县| 桐乡市| 天柱县| 南阳市| 巴中市| 温泉县| 门头沟区| 昌江|