浅谈python装饰器

在一些复杂的程序中,我们都能看到装饰器的身影。那装饰器到底有什么作用呢,他又是怎么工作的呢?

------------------------- 让我们来一探究竟--------------------------------

1、装饰器简单的使用
(1)作为一个函数装饰器

当我们我们需要重复利用代码时,可以通过一个函数来避免代码冗余。同时,也可以通过函数装饰器来解决。如果我们要实现下面这样一个功能(输出 函数的__name__ ),不使用装饰器的代码如下:

def logged(func):
    def wrapper(*args, **kwargs): 
        print('my name is %s'%(func.__name__))
        return func(*args, **kwargs)
    return wrapper
def func_1():
    print('END')
func_1 = logged(func_1)
func_1()
在ipython中,上面的输出结果是:
my name is func_1
END
同样的事情我们可以通过装饰器(@操作符)实现:
def logged(func):
    def wrapper(*args, **kwargs):
        print('my name is %s'%(func.__name__))
        return func(*args, **kwargs)
    return wrapper
@logged
def func_1():
    print('END')
func_1()

虽然在这么一个简单的函数中,并不能完全体现装饰器的优势。但是,当我们需要实现一个复杂操作的时候,使用<@装饰器>是不是会更简洁,更好一点呢,大家可以自己感受一下。

(2)带参数的装饰器

def logged(level):
    def decorator(func): 
        def wrapper(*args, **kwargs):
            if level == 'out': 
                print('my name is %s'%(func.__name__)) 
            return func(*args, **kwargs) 
        return wrapper
    return decorator
@logged(level = 'out')
def log(name = 'log'): 
    print('%s is running'%name)
log()
(3)类装饰器

类装饰器的封装性和灵活性实现具有更大的优势,还可以和内部函数结合。

class Name():
    def __init__(self, func):
        self._func = func
    def __call__(self):
        print('my name is zhangxiang')
        self._func()
@Name
def Print_Name():
    print('Get the name')
Print_Name()
在使用类装饰器的时候,主动调用内部函数__call__,所以最后的输出为:
my name is zhangxiang

Get the name

2、高级知识

先来看这样一个代码, 最后会输出什么结果呢?:

def logging(func): 
    def warpper(*args, **kwargs): 
        print('my name is %s'%func.__name__) 
        return func(*args, **kwargs) 
    return warpper
@logging
def add_two_numbers(x, y): 
    return x+y
print(add_two_numbers.__name__)
add_two_numbers(2,3)
最后输出的结果是:
warpper
my name is add_two_numbers

5

print(add_two_numbers.__name__)的结果怎么会输出warpper呢?难道不是输出add_two_numbers吗?
因为在使用装饰器的过程中,原函数的信息消失不见了,add_two_numbers被warpper取代了。在很多时候,这并不是我们所期望的。当需要原函数的一些信息,又该怎么处理呢??
我们可以载入functools.wraps,将原函数的元信息拷贝到装饰器中。

from functools import wraps
def logging(func):
    @wraps(func) 
    def warpper(*args, **kwargs): 
        print('my name is %s'%(func.__name__)) 
        return func(*args, **kwargs) 
    return warpper
@logging
def add_two_numbers(x, y): 
    return x+y
print(add_two_numbers.__name__)
add_two_numbers(2,3)
这时候结果变为了我们需要的了:
add_two_numbers
my name is add_two_numbers

5

------------------------------END--------------------------------

以上部分知识参考了知乎: 如何理解Python装饰器?问题下刘志军的回答。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值