python--Wrapper

Posted on 2018-09-26 10:49  eilinge  阅读(15166)  评论(0编辑  收藏  举报

  然后给大家介绍的是Wrapper(装饰器),使用广泛。python笔试,面试的话也会百分百问到的,基础和中级的知识储备还是必用的。

让我们开始。

先来一些基础相关知识

*args,**kwargs的区别

def function(x,y,*args,**kwargs):
    print(type(x))
    print(args)        
    print(kwargs)
    print(type(args))        
    print(type(kwargs))

function(1,2,3,4,5,a=1,b=2,c=3)

<type 'int'>
(3, 4, 5)                #*args返回的是数组
{'a': 1, 'c': 3, 'b': 2}    #**kwargs返回的字典
<type 'tuple'>
<type 'dict'>

正题开始

固定模板

装饰器:wrapper
模板:
def    装饰器名(func):                    #def 与 @之后的函数名称一致   调用函数func与ret=func(*args,**kwargs)内部函数一致
    def wrapper(*args,**kwargs):         #def 与 return 之后的函数名称一致
        ret = func(*args,**kwargs)            
        return ret                       #return ret 与 ret=func(*args,**kwargs)一致
    return wrapper

@装饰器名
def foo():
    pass
import time

def timmer(fun1):
    def wrapper(*args,**kwargs):
        start_time=time.time()
        res=fun1(*args,**kwargs)
        stop_time=time.time()
        print('run time is %s' %(stop_time-start_time))
        return res
    return wrapper

@timmer
def foo():
    time.sleep(3)
    print('from foo')

@timmer
def foo1():
    time.sleep(5)
    print('from foo1')

foo()
foo1()

 @wraps:避免被装饰函数自身的信息丢失

未添加@wraps

#-*- coding:utf-8 -*-
def decorator(func):
    def inner_function():
        pass
    return inner_function

@decorator
def func():
    pass

print(func.__name__)
#inner_function

添加@wraps

from functools import wraps

def decorator(func):
    @wraps(func) 
    def inner_function():
        pass
    return inner_function

@decorator
def func():
    pass

print(func.__name__)
#func
#@wraps:避免被装饰函数自身的信息丢失

多个装饰器的同时使用

def makebold(f):
    return lambda:'<b>'+f()+'</b>'
def makeitalic(f):
    return lambda:'<i>'+f()+'</i>'
def makeitalic1(f):
    return lambda:'<strong>'+f()+'</strong>'

@makebold
@makeitalic1
@makeitalic
def say():
    return 'hello'

print(say())
#<b><strong><i>hello</i></strong></b>
#多个装饰器的执行顺序:是从近到远依次执行。

类装饰器

#类装饰器
class Decorator(object):
    def __init__(self, f):
        self.f = f
    def __call__(self):
        print("decorator start")
        self.f()
        print("decorator end")

@Decorator
def func():
    print("func")

func()
'''
decorator start
func
decorator end
'''
import time

def decorator(func):
    def wrapper(*args,**kwargs):
        start_time = time.time()
        func(*args,**kwargs)
        end_time = time.time()
        print(end_time - start_time)
    return wrapper

class Method(object):

    @decorator 
    def func(self):
        time.sleep(0.8)

p1 = Method()
p1.func() # 函数调用
'''
0.815999984741
对于类方法来说,都会有一个默认的参数self,它实际表示的是类的一个实例,所以在装饰器的内部函数wrapper也要传入一个参数
- me_instance(任意参数)就表示将类的实例p1传给wrapper,其他的用法都和函数装饰器相同。
'''

较为复杂的多个装饰器 

import time

def deco01(func):
    def wrapper(*args, **kwargs):
        print("this is deco01")
        startTime = time.time()
        func(*args, **kwargs)
        endTime = time.time()
        msecs = (endTime - startTime)*1000
        print("time is %d ms" %msecs)
        print("deco01 end here")
    return wrapper

def deco02(func):
    def wrapper(*args, **kwargs):
        print("this is deco02")
        func(*args, **kwargs)
        print("deco02 end here")
    return wrapper

@deco01
@deco02
def func(a,b):
    print("hello,here is a func for add :")
    time.sleep(1)
    print("result is %d" %(a+b))

if __name__ == '__main__':
    f = func
    f(3,4)

'''
this is deco01
this is deco02
hello,here is a func for add :
result is 7
deco02 end here
time is 1032 ms
deco01 end here
'''
#多个装饰器执行的顺序就是从最后一个装饰器开始,执行到第一个装饰器,再执行函数本身。