Python 装饰器一说

装饰器Decorator,是在代码运行期间动态增加功能的方式,其实体现了一种设计模式即强调的是开放封闭原则,现对其定义不做多的说明,主要为其敲黑板记重点。


decorator就是一个返回函数的高阶函数。现模拟一个打招呼场景。

def SayHello(func):
    def how(*args, **kw):
        print('How about u %s' % func.__name__)
        return func(*args, **kw)
    return how

@SayHello
def Jack():
    print('I am fine')

Jack()

输出结果为:

How about u Jack
I am fine

我们在一开始定义了SayHello这个装饰器,参数接收函数并返回函数。根据语法知识,将@SayHello置于函数Jack()上方,且只能放在被装饰的函数的上方最近处,不能空行

当程序执行到函数Jack()时,则会开始执行@SayHello内的函数。
实际上是相当于执行了Jack= SayHello(Jack),此时变量名Jack则指向了内部函数指向的函数体内存地址,而不再指向它原来的函数体的内存地址。

内部函数how的参数定义是(*args, **kw),可以接受任意参数的调用。于是先打印出了How about u+Jack函数名,接着再调用回函数Jack()。


此时再次打印函数名Jack._name_时,会打印的不是原来的Jack()而是how(),具体原因可看上述,为了避免依赖于代码签名的程序报错,应在内部函数how()上面添加

@functools.wraps(func)


接下来拓展下如何编写能在函数调用的前后都有打印语句的写法

def SayHello(func):
    def how(*args, **kw):
        print('How about u? %s' % func.__name__)
        result = func(*args, **kw)
        print('I am fine too!')
        return result
    return how

@SayHello
def Jack():
    print('I am fine, and u?')

Jack()

打印结果为

How about u? Jack
I am fine, and u?
I am fine too!

要注意的是,result = func(*args, **kw)不能写为result = func,因为这表示将func函数的函数名当做参数传递给result,实际上是一个None值。


若原始参数需要参数呢,那我们就可以使用万能参数*args和**kw,比如从原始函数传递一个GoodMorning问候

def SayHello(func):
    def how(*args, **kw):
        print('How about u? %s' % func.__name__)
        result = func(*args,**kw)
        print('I am fine too!')
        return result
    return how

@SayHello
def Jack(today):
    print("%s, I am fine, and u?"%today)

Jack("GoodMorning ")

输出结果为

How about u? Jack
GoodMorning , I am fine, and u?
I am fine too!

若decorator本身需要传入参数,那就需要编写一个返回decorator的高阶函数,如传入一个时间

def funlog(time):
    def SayHello(func):
       def how(*args, **kw):
           print('%s' %time) 
           return func(*args,**kw)
       return how
    return SayHello

@funlog('2016-11-8')
def Jack():
    print("I am fine")

Jack()

输出结果为

2016-11-8
I am fine

一个原始函数也可以被多个函数修饰,但要注意@语法顺序

def SayHello(func):
    def One(*args, **kw):
        print('OneBegin' )
        result1 = func(*args,**kw)
        print('OneOver' )
        return result1
    return One
def SayHi(func):
    def Two(*args, **kw):
        print('TwoBegin' )
        result2 = func(*args,**kw)
        print('TwoOver' )
        return result2
    return Two

@SayHello
@SayHi
def Jack():
    print("Jack")

Jack()

输出结果如下

OneBegin
TwoBegin
Jack
TwoOver
OneOver
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值