Python装饰器的使用

Python当中所有东西都是对象,函数也不例外。所以要实现,在不改变一个函数的代码的情况下,给一个函数增加功能,可以在另一个函数里面调用这个函数,并执行别的功能。

def decorator(func):
    def wrapper():
        string = 'test'*2
        func()
        print(string)
    # 此处返回一个函数的意思是,返回处理这个函数的对象。    
    return wrapper

def test():
    print('本函数')

if __name__ == "__main__":
    # 此处接收处理这个函数的对象,并对其进行调用
    new_func = decorator(test)
    new_func()

而装饰器就是上面这段程序的实现

def decorator(func):
    def wrapper():
        string = 'test'*2
        func()
        print(string)
    return wrapper

@decorator
def test():
    print('本函数')

if __name__ == "__main__":
    test()

如果对一个函数调用多个装饰器,是由上往下的顺序,以递归的形式执行。这里可以使用pysnooper这个库,快速进行调试,查看执行的步骤。

import pysnooper

def order_test(func):
    def wrapper():
        print('+'*10)
        func()
        print('+'*10)
    return wrapper

def order_test_another(func):
    def wrapper():
        print('-'*10)
        func()
        print('-'*10)
    return wrapper

# @pysnooper.snoop()一个执行调试的库
@pysnooper.snoop(depth=3)
@order_test
@order_test_another
def ufunc():
    print('I am the func')

if __name__ == "__main__":
    ufunc()
输出结果
++++++++++
Starting var:.. func = <function order_test_another.<locals>.wrapper at 0x0000015F7AB45F28>
----------
14:57:10.321976 call         4     def wrapper():
I am the func
14:57:10.322972 line         5         print('+'*10)
----------
14:57:10.322972 line         6         func()
++++++++++
    Starting var:.. func = <function ufunc at 0x0000015F7AB45EA0>
    14:57:10.322972 call        11     def wrapper():
    14:57:10.322972 line        12         print('-'*10)
    14:57:10.322972 line        13         func()
        14:57:10.322972 call        21 def ufunc():
        14:57:10.322972 line        22     print('I am the func')
        14:57:10.322972 return      22     print('I am the func')
        Return value:.. None
    14:57:10.322972 line        14         print('-'*10)
    14:57:10.322972 return      14         print('-'*10)
    Return value:.. None
14:57:10.322972 line         7         print('+'*10)
14:57:10.322972 return       7         print('+'*10)
Return value:.. None

对带有参数的函数使用装饰器

def _decorator(func):
    def wrapper(cnt, sum):
        print('传入的参数为', cnt, sum)
        func(cnt, sum)
    return wrapper

@_decorator
def myfunc(cnt, sum):
    for i in range(cnt):
        sum += i
    print(sum)

if __name__ == '__main__':
    myfunc(8, 0)

结果

传入的参数为 8 0
28

当然,参数也可以使用*args, **kwargs 代替

def decorator(func):
    def wrapper(*args, **kwargs):
        print('传入的参数为', *args, **kwargs)
        func(*args, **kwargs)
    return wrapper


@decorator
def myfunc(cnt, sum):
    for i in range(cnt):
        sum += i
    print(sum)

if __name__ == '__main__':
    myfunc(8, 0)

在类中使用装饰器,即装饰的是一个方法,python中方法和函数的区别就是方法的第一个参数的self,即对象本身。类中的装饰器内置有staticmethod,classmethod,property。

def decorate_method(method_func):
    def wrapper(self, x):
        x -= 10
        return method_func(self, x)
    return wrapper

def decorate_staticmethod(method_func):
    def wrapper(x):
        x = x**2
        print('pow(x,2)=???')
        return method_func(x)
    return wrapper


class Test(object):
    def __init__(self):
        self.y = 15

    @decorate_method
    def sub(self, x):
        print('x - self.y', '=', x - self.y)

    @staticmethod
    @decorate_staticmethod
    def pow(x):
        print('x*x = ', end='')
        print(x)

if __name__ == '__main__':
    test = Test()
    test.sub(6)
    Test.pow(6)

使用嵌套的装饰器函数接收任意的参数,这样便可以不用为传入参数的活而烦恼。

def decorator_with_args(decorator_to_enhance):
    def decorator_maker(*args, **kwargs):
        def decorator_wrapper(func):
            return decorator_to_enhance(func, *args, **kwargs)
        return decorator_wrapper
    return decorator_maker


@decorator_with_args
def decorated_decorator(func, *args, **kwargs):
    def wrapper(function_arg1, function_arg2):
        print('Decorated with', args, kwargs)
        return func(function_arg1, function_arg2)
    return wrapper


@decorated_decorator(*list(range(10)))
def decorated_function(function_arg1, function_arg2):
    print('Hello', function_arg1, function_arg2)

decorated_function('Universe and', 'everything')

输出结果

Decorated with (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) {}
Hello Universe and everything
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值