13、python中的函数(闭包与装饰器)
一、嵌套函数
函数的内部又再定义另一个函数,这个函数就叫嵌套函数,里面含函数就叫内部函数。
示例:
二、返回函数
函数可以接收函数对象作为参数,同理函数也能返回一个函数对象作为返回值。
示例:
返回函数可以用来延迟函数的执行。
三、命名空间与变量作用域
变量作用域指的是变量的存活的范围。命名空间指的是属于一个对象的所有属性(对象)的集合。
示例:
A的命名空间是A函数对象里面的所有对象的集合,包括变量a、函数B、变量b;B的命名空间就是属于函数B的所有对象的集合,包括变量b;
a的变量作用域就是A的命名空间,b的变量作用域就是B的命名空间。
可以看出,命名空间就是对象的下一层的全部空间(比如A的命名空间就是A的下一层全部空间),变量作用域就是变量所处层的上一层对象的命名空间(比如a的作用域就是A的命名空间)。
四、闭包
一个嵌套函数的内部函数使用了内部函数以外的变量,这个嵌套函数就叫闭包。
示例:
闭包给我们一个重要的提示是,一个变量只要在作用域里面,它可以在内部函数中发挥作用。
五、装饰器
装饰器本质是一个函数,是一个返回函数的高阶函数,也是一个闭包。装饰器能解决的问题是:在一个原函数功能不变的情况下,为这个原函数增加一些新的功能。
比如说有一个打印我的名字的函数myname:
现在想在不改变myname的代码的情况下打印i come from foshan,这样就用到装饰器了:
事实上,我们不需要内部函数也可以为传入函数添加功能的:
这样做的话如果我们传入的func带有参数就用不了了,我们还可以这样:
这样的话虽然能传入带有参数的func,但新增加的功能与func的调用分开,这样也不妥。
所以我们的装饰器应该是集接收函数、返回函数、闭包为一身的函数,而且允许传入的函数带参数:
(*args,**kw)参数组表示可以传入任意的参数。
六、装饰器操作符@
定义了装饰器之后,我们就可以拿装饰器去应用在任意我们想增加相应功能的函数了:
为了使装饰器使用起来时更方便,主要为了代码看上去逻辑更清晰明了,于是便定义了@能直接调用参数,具体用法如下:
在函数定义前声明了@wherefrom这个语句后,在函数调用时就会执行一下逻辑:
myname = wherefrom(myname)
七、高级装饰器
我们在定义装饰器时,原函数是不能更改的。如果我们新增加的功能中还要网里面传入新参数,这种装饰器该怎么定义?思路很简单,本来两层的嵌套函数我们写够三层就可以了,第一层用于传入新参数,第二层用于传入函数:
(注意:这里的aplace和func传入的顺序不能改变,请想一下为什么。)
测试一下效果:
这里执行逻辑是:
myname = wherefrom("guangzhou")(myname)
八、装饰后的函数名字问题
无论是普通装饰器还是高级装饰器,在用了@这个操作符装饰函数后,在调用被装饰函数的时候,其函数名指向的具体的函数对象已经不是原来的函数对象了,就像上面的:myname = wherefrom(myname) 和 myname = wherefrom("guangzhou")(myname) 一样,函数名都指向了inner这个函数对象:
但有时候我们后续程序里可能会用调用到原函数的名字,如上面的myname.__name__这样,为了避免发生混淆,我们应该在装饰器定义时考虑这个事情:
我们在inner函数的代码毫无改动的情况下,把inner函数的名字指向了func函数的名字,所以我们能不能把这种新增功能定义成一个装饰器,用来提供给其他的装饰器定义时使用呢?python内部已经帮我们实现了这种功能:
functools中的wraps装饰器就是专门做这个的。有兴趣的可以看看wraps的源代码,看这个装饰器怎么实现的。
具体参考:
1、《核心编程第二版》第11章;
——————本篇完!
13、python中的函数(闭包与装饰器)的更多相关文章
- Python之面向对象:闭包和装饰器
一.闭包 1. 如果一个函数定义在另一个函数的作用域内,并且引用了外层函数的变量,则该函数称为闭包. def outter(): name='python' def inner(): print na ...
- python基础之函数当中的装饰器
在实际工作当中存在一个开放封闭原则 1.对扩展是开放的 为什么要对扩展开放呢? 我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改.所以我们必须允许代码扩展.添加新 ...
- python中对 函数 闭包 的理解
最近学到 函数 闭包的时候,似懂非懂.迷迷糊糊的样子,很是头疼,今天就特意查了下关于闭包的知识,现将我自己的理解分享如下! 一.python 闭包定义 首先,关于闭包,百度百科是这样解释的: 闭包是指 ...
- python学习总结---函数使用 and 装饰器
# 函数使用 ### 零碎知识 - 灵活的if-else ```python a = 3 if False else 5 print(a) ''' if False: a = 3 else: a = ...
- Python之命名空间、闭包、装饰器
一.命名空间 1. 命名空间 命名空间是一个字典,key是变量名(包括函数.模块.变量等),value是变量的值. 2. 命名空间的种类和查找顺序 - 局部命名空间:当前函数 - 全局命名空间:当前模 ...
- Python 变量作用域,闭包和装饰器
from dis import dis b = 6 def f1(a): print(a)print(b) b = 9 f1(3) print(dis(f1)) # dis模块可以查看python函数 ...
- python基础编程: 函数示例、装饰器、模块、内置函数
目录: 函数示例 装饰器 模块 内置函数 一.函数示例: 1.为什么使用函数之模块化程序设计: 不使用模块程序设计的缺点: 1.体系结构不清晰,可主读性差: 2.可扩展性差: 3.程序冗长: 2.定义 ...
- day20 函数闭包与装饰器
装饰器:本质就是函数,功能是为其他函数添加新功能 原则: 1.不修改被装饰函数的源代码(开放封闭原则) 2.为被装饰函数添加新功能后,不修改被修饰函数的调用方式 装饰器的知识储备: 装饰器=高阶函数+ ...
- Python中利用函数装饰器实现备忘功能
Python中利用函数装饰器实现备忘功能 这篇文章主要介绍了Python中利用函数装饰器实现备忘功能,同时还降到了利用装饰器来检查函数的递归.确保参数传递的正确,需要的朋友可以参考下 " ...
随机推荐
- Mysql的transaction实现(转)
(http://www.blogjava.net/i369/archive/2007/04/29/108906.html) transaction在数据库编程中是一个重要的概念,这样做可以控制对数据库 ...
- TeamViewer安装使用
1.下载安装包 官网下载最新安装包 2.安装步骤 3.连接 输入密码即可控制伙伴电脑.
- Struts2_Action
具体视图的返回可以由用户自己定义的Action来决定:具体的手段是根据返回的字符串找到对应的配置项,来决定视图的内容:具体Action的实现可以是一个普通的java类,里面有public String ...
- constrained属性
hibernate文档上是这么写的: constrained(约束) (可选) 表明该类对应的表对应的数据库表,和被关联的对象所对应的数据库表之间,通过一个外键引用对主键进行约束.这个选项影响save ...
- MSSQL复制分发对异构数据库之间大容量数据分发造成异常
由于历史遗留的问题,现有的架构中存在采用MSSQL的复制分发功能,从Oracle发布数据到MSSQL. 关于这项发布的实现原理,官方表述如下: Oracle 事务发布是通过使用 SQL Server ...
- JavaScript基础:逻辑运算符——&&和||(短路判断)和!
一.&&:所有条件都为true,返回true:只要有一个是false,返回false:不一定返回boolean类型值 1.可以操作任意类型的数据,不只是布尔型:(除了null.unde ...
- mysql在控制台里出现中文问号问题
由于重装了wampserver,之前遇到的问题统统会重新出现,那么今天遇到的是在mysql控制台中,在表里输入中文数据,却出现问号的问题: 那么这个就跟编码有关系了,那么,我们就去wampserver ...
- ABAP的include关键字,Java的import, C的include和C4C ABSL 的import比较
ABAP 使用关键字重复引入一个include program,会报syntax error: 原因是因为ABAP对include这个关键字的实现和其他编程语言有点不一样,在激活时简单地把被inclu ...
- 【JavaScript 封装库】BETA 3.0 测试版发布!
/* 源码作者: 石不易(Louis Shi) 联系方式: http://www.shibuyi.net =============================================== ...
- IOS 设置ipone状态栏的样式
/** 控制状态栏的样式 */ -(UIStatusBarStyle)preferredStatusBarStyle { //白色 return UIStatusBarStyleLightConten ...