廖雪峰的Python教程---装饰器

装饰器(Decorator)---- 是在代码运行期间动态增加功能的方式。本质上,decorator就是一个返回函数的高阶函数。

在面向对象(OOP)的设计模式中,decorator被称为装饰模式。OOP的装饰模式需要通过继承和组合来实现,而Python除了能支持OOP的decorator外,直接从语法层次支持decorator。Python的decorator可以用函数实现,也可以用类实现。

decorator可以增强函数的功能,定义起来虽然有点复杂,但使用起来非常灵活和方便。

1.无参数的装饰器

def log(func):
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper

@log
def now():
	print('2018-12-11')

 运行结果

                

2.有参数的装饰器

def log(text):
    def decorator(func):
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
    return decorator

@log('execute')
def now():
    print('2018-12-11')

运行结果:
                 

此时,会发现经过decorator装饰之后的函数,它们的__name__已经从原来的'now'变成了'wrapper': 

                    

Python内置的functools.wraps ()可以帮我们解决这个问题,代码改进如下:

import functools
def log(text):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
    return decorator

@log('execute')
def now():
    print('2018-12-11')

运行结果:

              

3.练习

(1)请设计一个decorator,它可作用于任何函数上,并打印该函数的执行时间

import time, functools
import functools

def metric(fn):
    @functools.wraps(fn)
    def wrapper(*args, **kw):
        t0 = time.time()
        result = fn(*args, **kw)
        print('%s executed in %.4f ms' % (fn.__name__, time.time() - t0))
        return result  # return fn(*args, **kw)
    return wrapper

# 测试
@metric
def fast(x, y):
    time.sleep(0.0012)
    return x + y;

@metric
def slow(x, y, z):
    time.sleep(0.1234)
    return x * y * z;

f = fast(11, 22)
s = slow(11, 22, 33)
if f != 33:
    print('测试失败!')
elif s != 7986:
    print('测试失败!')

 (2)请编写一个decorator,能在函数调用的前后打印出'begin call''end call'的日志

def log(func):
	def wrapper(*args,**kw):
		print('begin call:%s ' % func.__name__)
		c = func(*args,**kw)
		print('end call:%s ' % func.__name__)
		return c
	return wrapper

@log
def now():
	print('2018-12-11')

运行结果:

               

(3) 出一个@log的decorator,使它既支持

@log
def f():
	pass

又支持:

@log('execute')
def f():
	pass

代码如下:

import functools

def log(text=''):
	def decorator(func):
		@functools.wraps(func)
		def wrapper(*args,**kw):
			print('%s %s ' % (text,func.__name__))
			return func(*args,**kw)
		return wrapper
	return decorator

@log('execute')
def now():
    print('2018-12-11')

    
@log()
def now1():
	print('2018-12-11')

 运行结果:
                 

猜你喜欢

转载自blog.csdn.net/weixin_36793356/article/details/84961132
今日推荐