博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
第八章、函数进阶之装饰器02
阅读量:5291 次
发布时间:2019-06-14

本文共 4026 字,大约阅读时间需要 13 分钟。

目录

第八章、函数进阶之装饰器02

一、无参装饰器

1. 什么是装饰器?

装饰器指的是为被装饰对象添加功能,因此定义装饰器就是定义一个函数,只不过是该函数是用来为其他函数添加额外的功能

注意

  • 装饰器本身是可以任意调用的对象
  • 被装饰的对象也可以是任意可调用了的对象

2. 为什么要用装饰器

装饰器的实现必须遵循两大原则

  • 不修改被装饰的源代码

  • 不修改被装饰的对象的调用方式

    装饰器就是在遵循以上两个原则的前提下被装饰对象添加功能

    #真正的装饰器import timedef index():    print('您好啊!')    time.sleep(1)def deco(func):    # func = 原index    '''装饰器'''    def f1():    #重新创建后的index        start = time.time()        func()      #原index        end = time.time()        print(end-start)    return f1index = deco(index)index()     #f1

3. 怎么用装饰器

第一种传参方式:

def index():    print('welcome to index')    time.sleep(1)def time_count(func):    # func = 最原始的index    def wrapper():        start = time.time()        func()        end = time.time()        print(f"func time is {start-end}")    return wrapperf = time_count(index)f()#index = time_count(index)  # index为被装饰函数的内存地址,即index = wrapper#index()  # wrapper()
welcome to indexfunc time is -1.0008289813995361

下面方式是对第一种的再优化

第二种传参函数:包给函数——外包(指的是再定义命名为原函数的名字的变量,被赋予了原函数的内存地址,再调用被装饰后的函数名字(),以后就可以直接用原来函数的名字调用了)

import timedef index():    print('welcome to index')    time.sleep(1)def time_count(func):    # func = 最原始的index    def wrapper():        start = time.time()        func()        end = time.time()        print(f"{func} time is {start-end}")    return wrapper# f = time_count(index)# f()index = time_count(index)  # index为被装饰函数的内存地址,即index = wrapperindex()  # wrapper()
welcome to indexfunc time is -1.0008289813995361

4. 完善装饰器

上述的装饰器,最后调用index()(实际上是被装饰后的index())的时候,其实是在调用wrapper(),因此如果原始的index()有返回值的时候,wrapper()函数的返回值应该和index()的返回值相同,也就是说,我们需要同步原始的index()和wrapper()方法的返回值。 具体怎么做:

import timedef index():    print('welcome to index')    time.sleep(1)    return 123def time_count(func):    # func = 最原始的index    def wrapper():        start = time.time()        res = func()        end = time.time()        print(f"{func} time is {start-end}")        return res    return wrapperindex = time_count(index)res = index()print(f"res: {res}")
#此处return就已经把原始的index的返回值接收过来了        res = func()        end = time.time()        print(f"{func} time is {start-end}")        return res

welcome to index

<function index at 0x102977620> time is -1.0050289630889893

res: 123

如果原始的home()方法需要传参,那么我们之前的装饰器是无法实现该功能的,由于有timeinner()=home(),所以给timeinner()方法传参即可。

import timedef home(name):    print(f"welcome {name} to home page")    time.sleep(1)    return namedef time_count(func):    # func = 最原始的index    def timeinner(*args, **kwargs):        start = time.time()        res = func(*args, **kwargs)        end = time.time()        print(f"{func} time is {start-end}")        return res    return timeinnerhome = time_count(home)#就相当于把time_count()的函数返回值(其实是内部函数的地址)赋值给另一个变量名(其实就是被装饰后的原函数的名字)res = home('egon')#调用了timeinner("egon")print(f"res: {res}")

5. 装饰器语法糖

被装饰的函数正上方单独写上@装饰器名

import timedef time_count(func):    # func = 最原始的index    def wrapper():        start = time.time()        func()        end = time.time()        print(f"{func} time is {start-end}")    return wrapper@time_countdef index():    print('welcome to index')    time.sleep(1)
welcome to indexfunc time is -1.000335454940796

6. 装饰器模板

#双层装饰器def deco(func):    def wrapper(*args,**kwargs):        res = func(*args,**kwargs)        return res    return wrapper
#三层装饰器# 三层装饰器:给双层装饰器加参数def sanceng (engine):    def outter(func):        def wrapper(*args,**kwargs):  # wrapper是未来要运行的函数            #加功能            print(engine)            res = func(*args,**kwargs)  #func是被装饰的函数            return  res        return wrapper    return outter@sanceng('db')def shopping():    print('shopping')shopping()

二、有参函数

1. 三层闭包

# 三层装饰器:给双层装饰器加参数def sanceng (engine):    def outter(func):        def wrapper(*args,**kwargs):  # wrapper是未来要运行的函数            #加功能            print(engine)            res = func(*args,**kwargs)            print(res)#func是被装饰的函数            return  res        return wrapper    return outter@sanceng('db')def shopping(x="666"):    print('shopping')    return xshopping()
dbshopping666

转载于:https://www.cnblogs.com/demiao/p/11341403.html

你可能感兴趣的文章
sdut_1189
查看>>
归并排序
查看>>
机器视觉:SSD Single Shot MultiBox Detector
查看>>
走遍美国 —— 各州及其别名
查看>>
国内外免费电子书(数学、算法、图像、深度学习、机器学习)
查看>>
狄利克雷过程(Dirichlet Process)
查看>>
五子棋项目的实现(二)博弈树算法的描述
查看>>
Hibernate : Disabling contextual LOB creation as createClob() method threw error
查看>>
【bzoj4872】[Shoi2017]分手是祝愿 期望dp
查看>>
字符串元转分
查看>>
thinkphp 防sql注入
查看>>
201521123044 《Java程序设计》第1周学习总结
查看>>
MIT Scheme 的基本使用
查看>>
程序员的“机械同感”
查看>>
在16aspx.com上下了一个简单商品房销售系统源码,怎么修改它的默认登录名和密码...
查看>>
c++回调函数
查看>>
linux下Rtree的安装
查看>>
【Java】 剑指offer(53-2) 0到n-1中缺失的数字
查看>>
Delphi中ListView类的用法
查看>>
bzoj3110: [Zjoi2013]K大数查询 【树套树,标记永久化】
查看>>