python函数装饰器基础

1 python函数装饰器基础

python2.5开始支持函数装饰器。装饰器语法:@自动调用装饰器函数,返回可调用对象重新绑定到主体函数名。

1.1 基础用法

函数装饰器用法,@装饰器函数,下一行接def 主体函数:

@decorator
def fm(arg):
    pass
fm(8)

等价于

def fm(arg):
    pass
fm=decorator(fm)
fm(8)

decorator:装饰器函数,返回可调用对象,与fm具有相同数目参数;

fm:主体函数,作为入参后,重新赋值为decorator返回对象;

@decorator:自动调用装饰器函数,fm作为入参,将返回对象赋值给fm。

调用主体函数时,自动调用装饰器返回的对象,因为主体函数重新赋值为装饰器返回的对象。

即,fm(8)等价于decorator(fm)(8)

主体函数fm作为装饰器函数decorator的入参,通过@decorator自动调用装饰器函数decorator,装饰器函数返回可调用对象,并且赋值给主体函数fm。

装饰器函数decorator返回的可调用对象与主体函数fm有相同数目的入参。

函数装饰器不仅可以用在函数(function),还可以用在类方法(method)上。

比如类的静态方法@staticmethod,类的特性@property。

class C:
    @staticmethod
    def meth(...):
        pass
        
class C:
    @property
    def name(self):
        pass

1.2 返回和调用

python装饰器函数返回任意可调用对象给主体函数,可以是原函数或新的可调用对象。

返回不可调用对象报错

>>> def f_decorator(func):
    print('f_decorator被调用,返回不可调用对象')
    func()
    return (1,2)# 返回不可调用对象,之后调用报错

>>> @f_decorator
def testf():
    print('testf被调用')

    
f_decorator被调用,返回不可调用对象
testf被调用
>>> testf()
Traceback (most recent call last):
  File "", line 1, in <module>
    testf()
TypeError: 'tuple' object is not callable

返回原函数

>>> def f_decorator(func):
    print('f_decorator被调用,返回原函数')
    return func

>>> @f_decorator
def testf():
    print('testf被调用')

    
f_decorator被调用,返回原函数
>>> testf()
testf被调用

返回包装器

装饰器函数内定义一个嵌套函数,用作包装器,内部调用主体函数,返回包装器赋值给主体函数。func作为入参保持主体函数可以被调用。

>>> def f_decorator(func):
    print('f_decorator被调用,返回包装器')
    def f_wrapper(*args):
        print('f_wrapper被调用时,调用func')
        func(*args)
    return f_wrapper

>>> @f_decorator
def testf():
    print('testf被调用')

    
f_decorator被调用,返回包装器
>>> testf()
f_wrapper被调用时,调用func
testf被调用

通过类创建装饰器

构造方法接收主体函数,重写__call__()方法,并且调用主体函数。

@类名,自动将创建的实例对象赋值给主体函数名。

>>> class c_decorator:
    def __init__(self,func):
        self.func=func
    #实例调用小括号,会自动调用 __call__
    def __call__(self,*args):
        print('__call__ 被调用')
        self.func(*args)

# 自动将test_cd传递给构造函数,返回实例对象赋值给test_cd        
>>> @c_decorator
def test_cd():
    print('test_cd 被调用')

>>> test_cd()
__call__ 被调用
test_cd 被调用

通过类创建的装饰器用于装饰函数,不能装饰类方法。

>>> class c_decorator:
    def __init__(self,func):
        self.func=func
    def __call__(self,*args):
        print('__call__ 被调用')
        self.func(*args)
>>> class test_c:
    #无法将test_c的实例传递给test_m的self导致报错
    @c_decorator
    def test_m(self,*args):
        print('test_m 被调用')

        
>>> test_c().test_m()
__call__ 被调用
Traceback (most recent call last):
  File "", line 1, in <module>
    test_c().test_m()
  File "", line 6, in __call__
    self.func(*args)
TypeError: test_m() missing 1 required positional argument: 'self'

包装器装饰类方法

将传入的func保存到f_wrapper作用域,后面可以直接调用

>>> def f_decorator(func):
    print('f_decorator被调用,返回包装器')
    def f_wrapper(*args):
        print('f_wrapper被调用时,调用func')
        # 将传入的func保存到f_wrapper作用域
        # 供后面直接调用
        func(*args)
    return f_wrapper

>>> class test_c:
    @f_decorator
    def test_m(self,*args):
        print('test_m 被调用')

        
f_decorator被调用,返回包装器
>>> test_c().test_m()
f_wrapper被调用时,调用func
test_m 被调用

你可能感兴趣的:(python,python)