python装饰器

本文详细介绍了Python装饰器的概念和作用,通过实例展示了如何使用装饰器为函数添加额外功能,包括无参数和有参数的装饰器,以及装饰器的语法糖。同时,讨论了装饰器如何在不同场景下实现功能差异化。
摘要由CSDN通过智能技术生成

python装饰器

装饰器的作用就是在不修改函数的情况下为已存在函数添加额外功能。

举个例子,有两个函数test1和test2,我需要记录我每次执行的是哪个函数。下面是我一般的做法。

def test1():

    print "enter test1"

    print "hello"

 

def test2():

    print "enter test2"

print "world"

 

我们只是打印一下函数名,如果是更复杂一点的功能呢,这个就造成代码重复了

def test1():

print “hello”

 

def test2():

 print “world”

 

def logger(func):

print “enter %s” % func.__name__

func()

 

logger(test1)

logger(test2)

这个方法比上个好一点,利用了函数名作为实参(实参高阶函数)但是却改变了函数的调用方式。

 

下面这个方法是利用了返回值高阶函数,返回值中含有函数名

def test1():

print “hello”

 

def test2():

 print “world”

 

def logger(func):

print “enter %s” % func.__name__

return func

 

t1 = logger(test1)

t1()

 

t2 = logger(test2)

t2()

 

 

那么怎么写一个装饰器呢?根据上面的例子我们知道,函数名可以作为参数,并且可以作为返回值。装饰器其实是一个闭包,把函数作为参数并且返回一个替代函数。如下所示:

def logger(func):

    def wrapper()

        print "enter %s" % func.__name__

        return func()

    return wrapper

 

test1 = logger(test1)

test2 = logger(test2)

test1()

test2()

python version < 2.4时就是这样为函数增加额外的功能的。

这个其实就是装饰器,他对原函数进行包装,增加了额外的功能,并且返回了另一个函数。

后面版本的python支持了@语法糖。

'@'符号用作函数修饰符是python2.4新增加的功能,修饰符必须出现在函数定义前一行,不允许和函数定义在同一行。也就是说@A def f(): 是非法的。 只可以在模块或类定义层内对函数进行修饰,不允许修修饰一个类。一个修饰符就是一个函数,它将被修饰的函数做为参数,并返回修饰后的同名函数或其它可调用的东西。

2.4之后的版本有了语法糖,我们就可以这样写装饰器了。

def logger(func):

def wrapper()

    print "enter %s" % func.__name__

    return func()

return wrapper

 

@logger

def test1():

print hello

 

@logger

def test2():

print world

上面是一个简单的装饰器。

如果函数有参数,而添加的额外功能需要用到参数,我们可以用下面的方法:

def logger(func):

    def wrapper(*args, **kwargs):

     print "enter %s" % func.__name__

print "Arguments is %s, %s" % (args, kwargs)

     return func(*args, **kwargs)

    return wrapper

 

@logger

def test1(x, y=3):

    print "%s * %s = %s" % (x, y, x*y)

 

@logger

def test2(x, y):

    print "%s + %s = %s" %(x, y, x+y)

 

@logger

def test3(**kwargs):

print "kwargs: %s" % kwargs

 

如果同一个装饰器需要对不同函数有不同处理,那么就需要装饰器带参数, 用参数标记一下。例如我们代码里面的role_required装饰器。下面是个简单的例子:

def logger(parameter):

    print "Parameter is: %s" % parameter

    def outer(func):

print "outer wrapper"

def wrapper(*args, **kwargs):

     print "enter %s" % func.__name__

     print "Arguments is %s, %s" % (args, kwargs)

     return func(*args, **kwargs)

return wrapper

    return outer

 

@logger(parameter='test')

def test(x, y=3):

    print "%s * %s = %s" % (x, y, x*y)

 

print "================start===================="

test(2, 4)

 

运行结果如下:

Parameter is: test

outer wrapper

================start====================

enter test

Arguments is (2, 4), {}

2 * 4 = 8

首先logger(parameter)带参数,接收参数parameter,而@logger(parameter='test')刚好也是带一个参数的,就会执行这个函数。相当于:

logger = logger(parameter)

test = logger(test)

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值