在学习装饰器之前我们先了解下什么是闭包。

闭包

  • 函数引用
def test1(): print("--- in test1 func----")# 调用函数test1()# 引用函数ret = test1print(id(ret))print(id(test1))#通过引用调用函数ret()

运行结果:

--- in test1 func----140212571149040140212571149040--- in test1 func----

我们发现 test1() 和 test1 是有区别的,前者是直接调用函数,后者只是函数的引用.

  • 闭包
# 定义一个函数def test(number): # 在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包 def test_in(number_in): print("in test_in 函数, number_in is %d" % number_in) return number+number_in # 其实这里返回的就是闭包的结果 return test_in# 给test函数赋值,这个20就是给参数number,此时ret是 test_in 的引用ret = test(20)# 注意这里的100其实给参数number_inprint(ret(100))#注 意这里的200其实给参数number_inprint(ret(200))

运行结果:

in test_in 函数, number_in is 100120in test_in 函数, number_in is 200220

闭包实例

假如我们要求直线 y=ax+b 的长度.

# 第1种k = 1b = 2y = k*x+b# 缺点:如果需要多次计算,那么就的写多次y = k*x+b这样的式子y = k * 1 + by = k * 2 + b# 第2种def line_2(k, b, x): print(k*x+b)line_2(1, 2, 0)line_2(1, 2, 1)line_2(1, 2, 2)line_2(3,4,0)line_2(3,4,1)line_2(3,4,2)# 缺点:如果想要计算多次这条线上的y值,那么每次都需要传递k,b的值,麻烦print("-"*50)# 第3种: 全局变量k = 1b = 2def line_3(x): print(k*x+b)line_3(0)line_3(1)line_3(2)k = 11b = 22line_3(0)line_3(1)line_3(2)# 缺点:如果要计算多条线上的y值,那么需要每次对全局变量进行修改,代码会增多,麻烦print("-"*50)# 第4种:缺省参数def line_4(x, k=1, b=2): print(k*x+b)line_4(0)line_4(1)line_4(2)line_4(0, k=11, b=22)line_4(1, k=11, b=22)line_4(2, k=11, b=22)# 优点:比全局变量的方式好在:k, b是函数line_4的一部分 而不是全局变量,因为全局变量可以任意的被其他函数所修改# 缺点:如果要计算多条线上的y值,那么需要在调用的时候进行传递参数,麻烦print("-"*50)# 第5种:实例对象class Line5(object): def __init__(self, k, b): self.k = k self.b = b def __call__(self, x): print(self.k * x + self.b)line5_1_2 = Line5(1, 2)# 对象.方法()# 对象()line5_1_2(0)line5_1_2(1)line5_1_2(2)line5_11_22 = Line5(11, 22)line5_11_22(0)line5_11_22(1)line5_11_22(2)line5_1_2(3)# 缺点:为了计算多条线上的y值,所以需要保存多个k, b的值,因此用了很多个实例对象, 浪费资源print("-"*50)# 第6种:闭包def line_6(k, b): def create_y(x): print(k*x+b) return create_yline_6_1 = line_6(1, 2)line_6_1(0)line_6_1(1)line_6_1(2)line_6_2 = line_6(11, 22)line_6_2(0)line_6_2(1)line_6_2(2)

可以发现:

  • 匿名函数能够完成基本的简单功能,只有简单功能.
  • 普通函数能够完成较为复杂的功能,只有功能.
  • 闭包能够完成较为复杂的功能,包含功能和数据,传递的是数据+功能(即外层函数能保存接收的数据给里面的函数使用)
  • 对象能够完成最复杂的功能,包含很多数据和很多功能,传递的是数据+功能
  • 闭包也具有提高代码可复用性的作用.
  • 注意:由于闭包引用了外部函数的局部变量,导致外部函数的局部变量没有及时释放而消耗内存.

修改外部函数中的变量

# 使用关键字 nonlocal 即可修改外部函数的变量def func1(a): def func2(): nonlocal a a += 1 return a return func2

装饰器

装饰器本质上就是闭包,装饰器在不改变原函数的定义的条件下,给原函数扩展功能.

下面我们来分析这段代码:

1 def out(func):2 def inner():3 print('正在装饰')4 func()5 return inner6 @out7 def test():8 print('我被装饰啦!')9 test()

func 的执行调用过程

  1. 第1行:out 装饰器函数
  2. 第6行:底层实现 test = out(test) ,不会执行,需要等待
  3. 第7行:定义 func 函数对象
  4. 第6行:先执行右边,在执行左边.func-->test,test-->inner
  5. 第9行:test(),本质上调用 inner()
  6. 第3行
  7. 第4行
  8. 第8行

多个装饰器装饰一个函数

def message(func): print("1. 正在添加短信的装饰功能") def message_pay(): print("----正在做短信安全验证-----") func() return message_paydef gesture(func): print("2. 正在添加手势的装饰功能") def gesture_pay(): print("----正在做手势密码安全验证---") func() return gesture_pay# 短信安全验证 和 手势密码安全验证@gesture # pay = gesture(pay)@message # pay = message(pay)def pay(): print("---正在支付中---")# 装饰器装饰函数是自动执行pay()

打印结果:

1. 正在添加短信的装饰功能2. 正在添加手势的装饰功能----正在做手势密码安全验证-------正在做短信安全验证--------正在支付中---
  • 装饰的顺序:从内到外,就和我们平时穿衣服一样
  • 执行的顺序:从外到内,就和我们平时脱衣服一样

类装饰器

# 类对象可以的当做 装饰器函数class Person(object): def __init__(self, func): self.func = func def __call__(self, *args, **kwargs): # print("我被调用啦哟") self.func()# 类装饰器@Person # t = Person(t) 将函数当做参数传递 __init__() takes 1 positional argument but 2 were givendef t(): print("我是被装饰函数....")# 'Person' object is not callable# 调用对象 需要实现 __call__方法t()

类装饰器平时用的较少,了解即可

带参数的装饰器

def set_level(level): def set_fun(func): def call_func(): if level == 1: print("正在做手势安全验证.....") elif level == 2: print("正在做短信验证码验证.....") func() return call_func return set_fun@set_level(1) # 1. 调用函数 set_level(1), 返回set_fun, 2. 让set_fun作为装饰器函数 login = set_fun(login)def login(): print("-----正在登陆中-------")@set_level(2)def pay(): print("-----正在支付中-------")login()pay()

带参数的装饰器可以这样理解:,最外层将相当于一般的函数,只是将参数给里面的装饰器,实际上里面的闭包才是装饰器.

私信我获取 python 全套资料

「Python」一文读懂装饰器相关推荐

  1. python 最小二乘回归 高斯核_「机器学习」一文读懂线性回归、岭回归和Lasso回归...

    点击上方蓝色字体,关注AI小白入门哟 作者 | 文杰 编辑 | yuquanle 本文介绍线性回归模型,从梯度下降和最小二乘的角度来求解线性回归问题,以概率的方式解释了线性回归为什么采用平方损失,然后 ...

  2. 预测评价系统_「机器学习」一文读懂分类算法常用评价指标

    前言 评价指标是针对将相同的数据,输入不同的算法模型,或者输入不同参数的同一种算法模型,而给出这个算法或者参数好坏的定量指标. 在模型评估过程中,往往需要使用多种不同的指标进行评估,在诸多的评价指标中 ...

  3. 「科普」一文读懂生产制造MES系统

    谈及MES必须先谈生产,那什么是生成呢? 生产管理是通过对生产系统的战略计划.组织.指挥.实施.协调.控制等活动,实现系统的物质变换.产品生产.价值提升的过程. 生产管理是企业价值链的主要环节,是构成 ...

  4. 「项目实战」一文读懂思科网络设备IOS系统

    今天给大家带来的小知识是一文读懂思科的IOS系统,相信大家都有了解,但是今天呢给大家把完整的流程梳理出来,这样有助于大家记笔记哦! IOS是被用来传送网络服务并启动网络应用的.Cisco路由器的IOS ...

  5. 「Java基本功」一文读懂Java内部类的用法和原理

    内部类初探 一.什么是内部类? 内部类是指在一个外部类的内部再定义一个类.内部类作为外部类的一个成员,并且依附于外部类而存在的.内部类可为静态,可用protected和private修饰(而外部类只能 ...

  6. 「硬见小百科」一文读懂电子元器件

    用于制造或组装电子整机用的基本零件称为电子元器件,元器件是电子电路中的独立个体. 电子元件与器件有分别吗? 确实有人从不同角度把电子元器件区分为元件和器件. 有人从制造角度区分 元件:制造时没改变材料 ...

  7. 【Python】一文读懂Python正则表达式常用用法

    点击上方"AI遇见机器学习",选择"星标"公众号 重磅干货,第一时间送达 编辑:爱学AI 来源:geekvi   链接: www.segmentfault.co ...

  8. 最快最好用的数据增强库「albumentations」 一文看懂用法

    本文内容如下 1. Albumentations的自我介绍 2.案例欣赏 3.如何安装 4.有哪些数据增强方法 4.1 像素级变换(Pixel-level transforms) 4.2 空间级变换( ...

  9. 一文读懂 @Decorator 装饰器——理解 VS Code 源码的基础

    作者:easonruan,腾讯 CSIG 前端开发工程师 1. 装饰器的样子 我们先来看看 Decorator 装饰器长什么样子,大家可能没在项目中用过 Decorator 装饰器,但多多少少会看过下 ...

最新文章

  1. 学习利器:工欲善其事,必先利其器
  2. mongodb 内建用户
  3. 笔记-信息系统安全管理-安全审计
  4. 资深架构师十几年的架构干货经验总结分享!
  5. 含k个3的数(信息学奥赛一本通-T1090)
  6. SQL Server中的查询跟踪列值
  7. JavaScript之WebSocket 技术
  8. WIN7下odbc数据源配置问题
  9. 学习html+css+js笔记
  10. [原创] 婚纱照PS处理技术精粹(视频教程1.2G免费下载,11个核心技术点)
  11. SD卡和文件系统那些事儿
  12. Data-driven methods for solving algebra word problems论文阅读
  13. 用递归法实现多重网格法——MATLAB
  14. 头指针,头结点,首元结点的区别,头结点的优点
  15. docker安装Mysql
  16. Barcode读取之barcode_para_contrast_min.hdev
  17. GOG无法链接PSN:The connection to the server timed out
  18. 02.Python网络爬虫第二弹(http和https协议)
  19. ospf 的cost 与Metric
  20. python 视频转换图片

热门文章

  1. 统计应用计算机基础,计算机基础应用试题及答案参考
  2. linux 脚本设置时间戳,修改linux系统时间的方法(date命令)
  3. java函数定义的要素_Java学习笔记八(方法)
  4. 种豆得豆,种瓜得瓜 : 你的网络就是一片自留地
  5. 关于第十六届全国大学生智能汽车竞赛总决赛的规则建议
  6. 2021年春季学期-信号与系统-第八次作业参考答案
  7. 《李宏毅机器学习特训营》免费开放!直播教学!
  8. 黑洞是如何被拍照的?
  9. 第十一届全国大学生智能汽车竞赛获奖名单
  10. 如何配置Keil 外部编辑器?