首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 更多程式設計知識

九步掌握 Python 裝飾器:從入門到實戰

     編輯:更多程式設計知識

前言

裝飾器是 Python 進階編程的核心概念,廣泛用於日誌、權限驗證、緩存、計時等橫切關注點。本文通過九個遞進示例,帶你徹底理解裝飾器原理與寫法。

第一步:最簡單的函數

def myfunc():
    print("myfunc() called.")

myfunc()
myfunc()

第二步:用裝飾函數包裝

def deco(func):
    print("before myfunc() called.")
    func()
    print("after myfunc() called.")
    return func

def myfunc():
    print("myfunc() called.")

myfunc = deco(myfunc)  # 手動裝飾
myfunc()
myfunc()

第三步:語法糖 @

def deco(func):
    print("before myfunc() called.")
    func()
    print("after myfunc() called.")
    return func

@deco
def myfunc():
    print("myfunc() called.")

myfunc()
myfunc()

問題:裝飾邏輯只在導入時執行一次,原函數被多調用一次。

第四步:內嵌包裝函數(正確模式)

def deco(func):
    def _deco():
        print("before myfunc() called.")
        func()
        print("after myfunc() called.")
    return _deco

@deco
def myfunc():
    print("myfunc() called.")
    return 'ok'

myfunc()
myfunc()

第五步:裝飾帶參數函數

def deco(func):
    def _deco(a, b):
        print("before myfunc() called.")
        ret = func(a, b)
        print("after myfunc() called. result:", ret)
        return ret
    return _deco

@deco
def myfunc(a, b):
    print("myfunc(%s,%s) called." % (a, b))
    return a + b

myfunc(1, 2)
myfunc(3, 4)

第六步:裝飾不定參數函數(*args, **kwargs)

def deco(func):
    def _deco(*args, **kwargs):
        print("before %s called." % func.__name__)
        ret = func(*args, **kwargs)
        print("after %s called. result: %s" % (func.__name__, ret))
        return ret
    return _deco

@deco
def myfunc(a, b):
    return a + b

@deco
def myfunc2(a, b, c):
    return a + b + c

第七步:帶參數的裝飾器(三層嵌套)

def deco(arg):
    def _deco(func):
        def __deco():
            print("before %s called [%s]." % (func.__name__, arg))
            func()
            print("after %s called [%s]." % (func.__name__, arg))
        return __deco
    return _deco

@deco("mymodule")
def myfunc():
    print("myfunc() called.")

@deco("module2")
def myfunc2():
    print("myfunc2() called.")

第八步:裝飾器接收類參數(實現鎖機制)

class Locker:
    @staticmethod
    def acquire(): print("locker.acquire()")
    @staticmethod
    def release(): print("locker.release()")

def deco(cls):
    def _deco(func):
        def __deco():
            print("before %s called [%s]." % (func.__name__, cls))
            cls.acquire()
            try:
                return func()
            finally:
                cls.release()
        return __deco
    return _deco

@deco(Locker)
def myfunc():
    print("myfunc() called.")

myfunc()
myfunc()

第九步:多裝飾器疊加與模組化

# mylocker.py
class MyLocker:
    @staticmethod
    def acquire(): print("mylocker.acquire()")
    @staticmethod
    def unlock(): print("mylocker.unlock()")

class LockerEx(MyLocker):
    @staticmethod
    def acquire(): print("lockerex.acquire()")
    @staticmethod
    def unlock(): print("lockerex.unlock()")

def lockhelper(cls):
    def _deco(func):
        def __deco(*args, **kwargs):
            print("before %s called." % func.__name__)
            cls.acquire()
            try:
                return func(*args, **kwargs)
            finally:
                cls.unlock()
        return __deco
    return _deco

# 使用示例
from mylocker import *

class Example:
    @lockhelper(MyLocker)
    def myfunc(self):
        print("myfunc() called.")

    @lockhelper(MyLocker)
    @lockhelper(LockerEx)  # 疊加兩把鎖
    def myfunc2(self, a, b):
        print("myfunc2() called.")
        return a + b

if __name__ == "__main__":
    e = Example()
    e.myfunc()
    print(e.myfunc2(1, 2))

總結

裝飾器本質是 高階函數,接收函數返回函數。掌握「內嵌包裝函數保持簽名」「三層嵌套實現帶參裝飾器」「functools.wraps 保留元信息」三大核心技巧,即可靈活應對各種實戰場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved