1、闭包

①、python中一切皆对象,函数中嵌套函数肯定也是合理的,这种函数也叫作内嵌函数(内部函数)

②、内嵌函数只能被外部函数调用,被外部函数以外的区域被调用,就会出错!!!

③、若内部函数中引用了外部函数的变量,或者外部函数以外的变量,那么!!这个内部函数就叫做闭包

例子:

④、闭包的作用:定义-->闭包可以将其自己的代码和作用域以及外部函数的作用结合在一起

按照上面的例子通俗的理解闭包就是:

1 本来count仅实现了两个数量相加的功能
2
3 由于闭包函数sum,给这个原有的的功能上又新增了一个功能
4
5 因此可得,增加了闭包函数,在不改变原有功能的情况下修饰了原有函数,。使函数的功能可以变得更丰富---->由此引入装饰器的概念,其实和闭包的作用都是一样的,都是为了装饰原有函数的功能

2、装饰器

①、理解了上述闭包的概念,那么其实装饰器的本质也是一个函数(确切的说是一个闭包函数)

②、常见使用场景:插入日志(这个在测试过程中有用)、性能测试、事务处理、权限校验

③、用法:创建一个装饰器,其实就是创建一个普通def函数

④、有返回值的函数被装饰之后依然有返回值,没有返回值的函数被装饰之后则没有返回值,符合我们想要的结果。

  #装饰器不正规的书写方法
def decorator(func):----->装饰器的参数是一个方法(方法名),
func()
print('this is decorator')---->正常情况下,装饰器初始化完成,装饰器应该(return)返回一个可调用的对象,很明显,这边没有 @decorator
def target():---->原功能函数,其功能是打印一段文字
print('this is target')
target;---------->执行原功能函数时,若这个函数带有@装饰器,那么会直接开始执行这个装饰器函数,并把原函数当做参数传入;注意:此处的函数的调用方法是错误的,但是使用正确的调用方法会报错,下面会解释
#最终输出

问题:我发现如果执行原函数时使用target(),会提示TypeError: 'NoneType' object is not callable错误,但是去掉括号,直接用target调用,则正常,这又是为什么呢?有没有人知道可以解答一下呢??

原理:会发生上面错误的原因,不是因为装饰器的代码写的不对,并非错误,只不过是一种不友好的装饰器,这就是为什么明明使用的是错误的调用方法,但是仍然能运行,那是因为我们把装饰器函数写成了不可被调用的函数。具体:https://www.tuicool.com/articles/FBZvya

因此!!!把上面的代码改为:

#装饰器的正确格式
def decorator(func):
def dec2():
func();
print('this is decorator');
return dec2;------------->装饰器返回一个函数(而函数是可调用的对象)~上面的写法返回的对象是str对象,是不可调用的 @decorator
def target():
print('this is target')
target();------->此处使用正确的调用函数方法,正常运行。
 

3、装饰器的具体实践例子


 #通过银行卡存取款来模拟
#一个函数里又实现了另外一个函数,这样实际已经违背了函数的开放封闭原则 # 以下方法实现了在不改变原函数功能,以及原函数的调用方式的情况下,拓展了原功能的功能
# 那么注意现在:除了check_mima(func)这个方法以外,其他方法不能再动了!!!!!!!!,这样才能真正理解到装饰器的魅力丫 #以下方法实现了在不改变原函数功能,以及原函数的调用方式的情况下,拓展了原功能的功能
#注意看下面优化后的函数,是不是很熟悉,内部函数使用了外部函数的变量(func),所以这是一个闭包啊
def check_mima(func):
def inner():
print('密码校验中')
func();
return inner; @check_mima
def cunkuan():
#check_mima();
print('存款中.....'); @check_mima
def qukuan():
#check_mima();
print('取款中...'); #qukuan=check_mima(qukuan);
#cunkuan=check_mima(cunkuan); #一个简单的方法,按下按钮1则存款,否则为取款(方法简单粗暴)
#在存取款操作之前加上了密码校验,但明显代码冗余还是很高
#可想而知,如果再加上查询、等其他业务,代码的冗余岂不是越来越高 button=1;
if button==1: qukuan();
else:
cunkuan();

##

###########################装饰器装饰有参数的函数
 #装饰器装饰有参数的函数
#按照下面的写法看似没有问题,实际会返回错误:inner() takes 0 positional arguments but 1 was given
#看报错原因就知道,inner()函数多了一个参数。大家一定要注意一点,因为装饰器函数的返回值是inner,可以看成inner()==aa()
#所以inner()的输入、输出的类型!必须和aa一模一样!!!!!!!!!
def zhuangshi(func):
def inner():
func();
print('装饰一下');
return inner;
@zhuangshi
def aa(a):
print('哈哈',a); aa(2);

##因此把上面代码修改如下(注意红字部分):

 def zhuangshi(func):
def inner(str):
func(str);
print('装饰一下');
return inner;
@zhuangshi
def aa(a):
print('哈哈',a); aa(2);

###########################装饰器装饰有返回值(return)的函数
1、因为inner函数不会有return
2、但是重点是inner()的返回值,必须必须要跟被装饰函数一样
3、所以原函数有return返回值
4、所以inner函数也要有返回值
 

python--闭包、装饰器的更多相关文章

  1. Python闭包装饰器笔记

    Python三大器有迭代器,生成器,装饰器,这三个中使用最多,最重要的就是装饰器.本篇将重要从函数嵌套开始讲起,从而引入闭包,装饰器的各种用法等. python中的一切都是一个对象(函数也是) 1.首 ...

  2. python 闭包@装饰器

    1.装饰器 装饰器(Decorator)相对简单,咱们先介绍它:“装饰器的功能是将被装饰的函数当作参数传递给与装饰器对应的函数(名称相同的函数),并返回包装后的被装饰的函数”,听起来有点绕,没关系,直 ...

  3. python闭包&装饰器&偏函数

    什么是闭包? 首先还得从基本概念说起,什么是闭包呢?来看下维基上的解释: 在计算机科学中,闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数.这个被引用的 ...

  4. python 闭包&装饰器(一)

    一.闭包 1.举例 def outer(): x = 10 def inner(): # 内部函数 print(x) # 外部函数的一个变量 return inner # 调用inner()函数的方法 ...

  5. 【Python】 闭包&装饰器

    python中的函数本身就是对象,所以可以作为参数拿来传递.同时其允许函数的层级嵌套定义,使得灵活性大大增加. 闭包 闭包的定义:将函数的语句块与其运行所需要的环境打包到一起,得到的就是闭包对象.比如 ...

  6. Python 进阶_闭包 & 装饰器

    目录 目录 闭包 函数的实质和属性 闭包有什么好处 小结 装饰器 更加深入的看看装饰器的执行过程 带参数的装饰器 装饰器的叠加 小结 装饰器能解决什么问题 小结 闭包 Closure: 如果内层函数引 ...

  7. Python各式装饰器

    Python装饰器,分两部分,一是装饰器本身的定义,一是被装饰器对象的定义. 一.函数式装饰器:装饰器本身是一个函数. 1.装饰函数:被装饰对象是一个函数 [1]装饰器无参数: a.被装饰对象无参数: ...

  8. 【转】详解Python的装饰器

    原文链接:http://python.jobbole.com/86717/ Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现 ...

  9. python 基础——装饰器

    python 的装饰器,其实用到了以下几个语言特点: 1. 一切皆对象 2. 函数可以嵌套定义 3. 闭包,可以延长变量作用域 4. *args 和 **kwargs 可变参数 第1点,一切皆对象,包 ...

  10. 详解Python的装饰器

    Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现了say_hello()和say_goodbye()两个函数. def sa ...

随机推荐

  1. Linux内存使用调整

    前段时间在做播放器的时候,遇到个问题,花了很长时间,做个记录,希望对有需要的人有所帮助: 播放器的播视频的时候,无论是手动切换视频还是到视频播放完成,自动切换视频,一定次数后均出现黑屏现象,偶尔有声音 ...

  2. [转载]RabbitMQ消息可靠性分析

    有很多人问过我这么一类问题:RabbitMQ如何确保消息可靠?很多时候,笔者的回答都是:说来话长的事情何来长话短说.的确,要确保消息可靠不只是单单几句就能够叙述明白的,包括Kafka也是如此.可靠并不 ...

  3. 搭建python的虚拟环境

    文章连接:https://www.cnblogs.com/zlsgh/p/8485848.html ubuntu系统下Python虚拟环境的安装和使用        前言:进行python项目开发的时 ...

  4. JS将图片转换成Base64码

    直接上代码 html页面代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...

  5. Go语言环境安装&搭建(Linux)

    Linux的东西果然不记不行啊~ 下载&安装 下载 我们先找到linux版的下载链接 https://golang.org/dl/ 打开网址找到Linux对应的链接右键复制下载地址 然后连接服 ...

  6. 洛谷P5162 WD与积木 [DP,NTT]

    传送门 思路 真是非常套路的一道题-- 考虑\(DP\):设\(f_n\)为\(n\)个积木能搭出的方案数,\(g_n\)为所有方案的高度之和. 容易得到转移方程: \[ \begin{align*} ...

  7. Confluence 6 CSS 指南:修改顶部背景

    Confluence 默认页面的顶部是有关站点的菜单连接,在这里定义了 快速连接, 浏览菜单,用户菜单和快速查找输入框.在这个示例中,我们将会尝试修改顶部的菜单部分的背景和一些自定义的图片. 创建一个 ...

  8. STL的基本操作指令

    list :Lists将元素按顺序储存在链表中. 与 向量(vectors)相比, 它允许快速的插入和删除,但是随机访问却比较慢. assign() 给list赋值 back() 返回最后一个元素 b ...

  9. java String正则表达式

    1.正则表达式 字符串替换,     例子; String s="131hello334thrid  ".replaceAll("[a-zA-Z]"," ...

  10. 解决Xshell不从22端口连接服务器

    xshell默认是22端口 如果服务器给的ssh端口不是22,会连接失败 需要去指定连接 新建 设置ip和端口,点下面的确定 双击刚创建的会话 输入用户名密码 连接成功