装饰器笔记整理

装饰器

1.装饰器说明

当需要在多段不同程序中执行相同的操作,就需要装饰器

2.装饰器的使用方法

需要将要装饰的函数作为函数传递,装饰器里嵌套函数,返回值是嵌套的函数对象
例:
def desc(fun):
    def add_info():           
        print("开学不快乐")
        fun()  # login()
        print("欢迎来到西安没电大学")
    return add_inf

3.装饰器的两种调用方式:

完整代码:

def login():
     print("中秋节快乐")
login()
方法一:语法糖

@desc (语法糖) 实际上是login = desc(login)

方法一:调用函数,返回值是函数

login = desc(login)

返回结果:

开学不快乐
中秋节快乐
欢迎来到西安没电大学

4.带有多个装饰器的函数

当使用装饰器时,调用的顺序与装饰器的先后位置有关,在上方的装饰器后调用,在下方的装饰器先调用,而装饰器里嵌套的函数如装饰器一里的wrapper1和装饰器二里的wrapper2,执行时,先执行wrapper1,再执行wrapper2
例:

def print_i(fun):
    print("我是第一个装饰器")
    def wrapper1(*args, **kwargs):
        print("我是第二个装饰器里的嵌套函数")
        return  fun(*args, **kwargs)  # wrapper
    return  wrapper1

def print_j(fun):   # fun=login
    print("我是第二个装饰器")
    def wrapper(*args, **kwargs):
        print("我是第二个装饰器里的嵌套函数")
        return  fun(*args, **kwargs)
    return  wrapper
@print_i  调用了第一个装饰器
@print_j  调用了第二个装饰器
def login():
    return "看上面,别看我"
print(login())
我是第二个装饰器   >>先调用了位置在后面的装饰器
我是第一个装饰器     >>再调用了位置在前面的装饰器
我是第一个装饰器里的嵌套函数  >>先执行位置在前的装饰器里的嵌套函数
我是第二个装饰器里的嵌套函数  >>后执行位置在后的装饰器里的嵌套函数
看上面,别看我

5.使用装饰器时函数属性发生变化的情况及解决方案

当使用装饰器时,因为将函数传给了装饰器里的嵌套函数,所以函数的属性会随之而变,变为装饰器内嵌套函数的属性
例:
import time
def timeit(fun): 
    def wrapper(*args, **kwargs):
            start_time = time.time()
            res = fun(*args, **kwargs)  
            end_time = time.time()
            print("运行时间为:%.6f" % (end_time - start_time))
            return res
   return wrapper
@timeit
def fun():
    print("hello")
print(fun.__name__)
print(fun.__doc__) 
wrapper
这是一个wrpper函数
由上可见,当调用装饰器后,函数的函数名和帮助文档也会随着改变,为了让函数保留其性质,可以调functools函数
import time
import functools
def timeit(fun): 
    @functools.wraps(fun)  >>声明将fun函数的性质还给fun
    def wrapper(*args, **kwargs):
            start_time = time.time()
            res = fun(*args, **kwargs)  
            end_time = time.time()
            print("运行时间为:%.6f" % (end_time - start_time))
            return res
   return wrapper
@timeit
def fun():
    print("hello")
print(fun.__name__)
print(fun.__doc__) 
fun
None

6.当装饰器中含有参数时:

import functools
import time
def log(kind):  # kind="debug"
    def add_log(fun):
        @functools.wraps(fun)
        def wrapper(*args, **kwargs):
            # run_time = time.ctime()
            # fun_name = fun.__name__
            start_time = time.time()
            res = fun(*args, **kwargs)
            end_time = time.time()
            print("<%s> [%s] 函数名: %s, 运行时间:%.5f, 运行返回值结果:%d"
                  %(kind, time.ctime(), fun.__name__, end_time-start_time, res )
                  )
            return res
        return wrapper
    return  add_log
@log("debug")
#  log("debug")==> 返回值是add_log
#  add=add_log(add)
def add(x,y):
    time.sleep(0.1)
    return x+y
print(add(1,2))
<debug> [Wed Aug 22 14:26:36 2018] 函数名: add, 运行时间:0.10018, 运行返回值结果:3
3

7.装饰器的应用

例:装饰器实现计时器,检测列表生成式和map的效率高低
import random
import string
import time
li = [ random.choice(string.ascii_letters) for i in range(100)]
def timeit(fun): # fun_list
    def wrapper(*args, **kwargs):   
        start_time = time.time()
        fun(*args, **kwargs) 
        end_time = time.time()
        print("运行时间为:%.6f" % (end_time - start_time))
    return  wrapper
@timeit   
def fun_list(n):
    print([2*i for i in range(n)])
@timeit
def fun_map(n):
    print(list(map(lambda x:x*2, range(n))))
fun_list(5)   
fun_map(5)
[0, 2, 4, 6, 8]
运行时间为:0.000021
[0, 2, 4, 6, 8]
运行时间为:0.000007
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值