标签:
装饰器自身就是一个函数,它是在函数上调用的装饰,也可以说用一个函数(装饰器)来”装饰”另一个函数。在代码中以@表示,很明显的是在某个函数之上出现了@,就说明装饰器装饰了其函数。重点来了,那么它为什么叫做装饰器呢?
>>> import time >>> def extend_login(func): >>> def timestamp(*args,**kwargs): >>> print (time.ctime()) #打印当前系统时间 >>> func(*args,**kwargs) >>> return timestamp #注意这里不能加括号,因为return的是timestamp的内存地址,不可写为timestamp() >>> >>> @extend_login >>> def login(username): >>> print ("%s login system" % username) >>> >>> login(‘Stanley‘)
以上代码中,extend_login 就是装饰器的名称,它是一个函数,接收func作为这个函数的参数。因为在执行exntend_login函数的时候,并没有立即执行timestamp函数,而是将timestamp生成内存地址(图1),下一步直接return了timestamp的内存地址到login函数,此时的login函数已经不再是原来的它,经过了extend_login函数的装饰,已经变为了login = extend_login(login),这里的login是其内存地址;最后执行执行login函数(也就是timestamp函数。所谓装饰器是指在执行func函数之前,又执行了其他的操作(打印当前系统时间),所以说起到了装饰func函数的作用,其功能是在用户登陆之前,打印当前系统时间,这就是一个装饰器。
图1
装饰器到底有什么使用的场景能让它物有所用呢,大多数的场景是在函数不修改原有函数的基础上,在其外部扩展一个函数的行为,修改函数或扩展原有功能;另一方如果这个功能可以被使用在很多函数上,或是函数并不是自己实现,那可以写个装饰器来实现这些功能,而不用重复编写,减少代码的冗余度。
>>> @extend_login >>> def login(): >>> pass
在装饰器使用过程中,@extend_login含义是调用名为exntend_login的装饰器(其实就是个函数)来装饰login函数,那么按照如上调用等价于:
>>> login = extend_login(login) #这里括号内的login没有(),仅仅是吧login的内存地址当做参数传递给extend_login装饰器(函数)
在给装饰器内传递参数的时候,需要注意的是在timestamp函数内,要写多个接收参数和接收任意类型参数,也就是*args和**kwargs;如果这里没有指定接收参数,那么在login函数向装饰器内传递参数会出现报错。
>>> import time >>> def extend_login(func): >>> def timestamp(): #没有参数会报错 >>> print (time.ctime()) >>> func() #没有参数会报错 >>> return timestamp >>> >>> @extend_login >>> def login(username): >>> print ("%s login system" % username) >>> >>> login(‘Stanley‘) TypeError: timestamp() takes no arguments (1 given)
在装饰器调用中,会把login函数的参数传递给装饰器(图2)
图2
>>> import time >>> def extend_login(func): >>> def timestamp(*args,**kwargs): >>> print (time.ctime()) >>> func(*args,**kwargs) >>> return timestamp >>> >>> @extend_login >>> def login(username): >>> print ("%s login system" % username) >>> >>> login(‘Stanley‘) Mon Feb 01 11:29:40 2016 Stanley login system
基本类型装饰器的实现类似于此,一个函数被多个装饰器装饰等高级用法还会陆续更新。
标签:
原文地址:http://www.cnblogs.com/stanley-liu310/p/5176442.html