python装饰器

装饰器实际上就是一种在程序运行期间动态地增加功能的方式,
它既不修改被装饰函数的源代码,也不改变原函数的调用方式
例如现有一个time()函数:

def time():
	print('12:00')

由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数:

now = time
now()

结果:

12:00

本质上装饰器就是一个返回函数的高阶函数
现在希望time()函数可以增加一个输出日期的功能,但又不修改原本的定义,可以设定一个装饰器:

def date(func):
	def wrapper(*args, **kw):
		print('2018-12-18')
		return func(*args, **kw)
	return(wrapper)

date即为一个装饰器,接受一个函数作为参数,并返回一个函数
使用python的@语法将装饰器放在所要装饰的函数上:

@date
def time():
	print('12:00')
time()

结果:

2018-12-18
12:00

@date放在所装饰的函数上面 等价于 time = date(time)
由于date()是一个装饰器,返回一个函数,所以,原来的time()函数仍然存在,只是现在同名的time变量指向了新的函数,于是调用time()将执行新函数,即在date()函数中返回的wrapper()函数。

wrapper()函数的参数定义是(*args, **kw),因此,wrapper()函数可以接受任意参数的调用。在wrapper()函数内,首先输出日期,再紧接着调用原始函数。

如果装饰器本身需要传入参数,那就需要定义一个返回装饰器的高阶函数。例如,要自定义data的文本:

def date(text):
	def decorator(func):
		def wrapper(*args, **kw):
			print('{}:2018-12-18'.format(text))
			return func(*args, **kw)
		return(wrapper)
	return decorator

进行装饰:

@date('runtime')
def time():
	print('12:00')
time()

结果:

runtime:2018-12-18
12:00

此时的 @date(‘runtime’) 等价于 time = date(‘runtime’)(time)
首先执行time(‘runtime’),返回的是decorator函数,再调用返回的函数,参数是time函数,返回值最终是wrapper函数。
现在使用函数对象内置的 __name__属性(可以得到函数的名字) 来看看用装饰器装饰过后的函数属性是否会发生变化:

print(time.__name__)

结果:

wrapper

发现函数名由原来的time变成了wrapper,此时应使用python内置的functools.wraps将原始函数time()的__name__等属性复制到wrapper()函数中:

import functools
def date(text):
	def decorator(func):
		@functools.wraps(func)
		def wrapper(*args, **kw):
			print('{}:2018-12-18'.format(text))
			return func(*args, **kw)
		return(wrapper)
	return decorator

即在定义wrapper函数前加一句 **@functools.wraps(func)**就可以了。

如要要实现将不带参数的装饰器和带参数的装饰器合并一起,可参考如下写法:

import functools
def date(text):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kw):
            print('{}:2018-12-18'.format(text) if not callable(text) else '2018-12-18')
            return func(*args, **kw)
        return wrapper
    return decorator(text) if callable(text) else decorator

callable(text) 作用是判断参数对象text是否为可回调对象,是的话返回True,否则返回False

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值