python tips:最内嵌套作用域规则,闭包与装饰器
在作用域与名字空间提到,python是静态作用域,变量定义的位置决定了变量作用的范围。变量沿着local,global,builtins的路径搜索,直觉上就是从里到外搜索变量,这称为最内嵌套作用域规则。
从里到外的搜索
a = 1 def f():
a = 2
def b():
print(a)
b() f()
输出结果
2
最内嵌套作用域规则有一个神奇的特性,它对local变量的搜索只依赖于静态代码的组成,而与代码如何调用没有关系。
闭包
a = 1 def f():
a = 2
def b():
print(a)
return b b = f()
b()
输出结果
2
函数f返回函数b,在第九行调用f得到函数b,此时函数f调用完成,应该被销毁,它包含的局部变量a也应该随之销毁。所以调用函数b时应该得不到函数f的变量a才对,事实却相反,函数b打印出了本应被销毁的a变量。
局部作用域是静态实现的,跟代码如何调用,何时调用没有关系。对于局部变量a来说,它的作用域是函数f内,当然包含了函数b。而且在函数b中确实引用了a,为了让b在任何时候都能够得到它,a会将自己绑定到函数b上。
这样b得到了一个额外的变量a,在函数f被销毁后,仍然能够使用变量a。这种变量与函数绑定的结果称为闭包(closure),这种绑定的变量是静态变量(类似于为函数添加了属性)。
直观上,闭包的作用就是为函数添加静态变量。
函数计数器
def fn():
print("call fn") def count(fn):
i = [0]
def s(*arg):
i[0] += 1
print(f"times: {i[0]}")
fn(*arg)
return s fn = count(fn)
for _ in range(5):
fn()
输出结果
times: 1
call fn
times: 2
call fn
times: 3
call fn
times: 4
call fn
times: 5
call fn
有了闭包,不用传入额外的参数,函数自身就能记住状态的变化(闭包提供静态变量)。
装饰器
def count(fn):
i = [0]
def s(*arg):
i[0] += 1
print(f"times: {i[0]}")
fn(*arg)
return s @count
def fn():
print("call fn") for _ in range(5):
fn()
装饰器其实就是一个语法糖,fn上方加@count,等价于fn = count(fn)。
计数功能仍靠闭包实现。
@count必须出现在count定义函数之后,否则无法识别。
总结:
1. 最内嵌套作用域对于local变量的搜索只与代码组成有关,与动态运行环境无关
2. 闭包是外层变量与内层函数的绑定结果,主要作用是位函数添加静态变量
3. 装饰器是语法糖,装饰函数一般都返回一个闭包。
python tips:最内嵌套作用域规则,闭包与装饰器的更多相关文章
- 一文搞懂Python函数(匿名函数、嵌套函数、闭包、装饰器)!
Python函数定义.匿名函数.嵌套函数.闭包.装饰器 目录 Python函数定义.匿名函数.嵌套函数.闭包.装饰器 函数核心理解 1. 函数定义 2. 嵌套函数 2.1 作用 2.2 函数变量作用域 ...
- python 基础之第十天(闭包,装饰器,生成器,tarfile与hashlib模块使用)
局部变量与全局变量 局部变量:在函数里面定义的,只有当函数活动时才生效 全局变量:不在函数里面的 In [1]: x=10 In [2]: def bar(): ...: x=20 ...: prin ...
- Python--高阶函数、函数嵌套、名称空间及变量作用域、闭包、装饰器
1.高阶函数(map/reduce/filter) 高阶函数是指函数的参数可以是函数 这篇总结几个常用的高阶函数:map/reduce/filter map函数.reduce函数.filter函数都是 ...
- Python 变量作用域,闭包和装饰器
from dis import dis b = 6 def f1(a): print(a)print(b) b = 9 f1(3) print(dis(f1)) # dis模块可以查看python函数 ...
- 周末学习笔记——day01(函数,函数对象,嵌套调用,名称空间,作用域,闭包,装饰器)
一,复习 字符编码 文件头:py2—ASCII,py3—UTF-8 三种字符串:u' ' b ' ' r ' ' u' ' .endcode(' utf-8 ') b' '.deconde(' utf ...
- Python 名称空间与作用域、闭包与装饰器
Python 的名称 Python 的名称(Name)是对象的一个标识(Identifier).我们知道,在 Python 里面一切皆对象,名称就是用来引用对象的.说得有点玄乎,我们以例子说明. 例如 ...
- python函数作用域,闭包,装饰器
第一:函数作用域: L:local 函数内部作用域 E:enclosing 函数内部与内嵌函数之间(闭包) G:global 全局作用域 B:build_in ...
- python中的生成器、迭代器、闭包、装饰器
迭代器 迭代是访问集合元素的一种方式.迭代器是一个可以记住遍历的位置的对象.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退. 可迭代对象 以直接作用于 for ...
- Python进阶(五)----内置函数Ⅱ 和 闭包
Python进阶(五)----内置函数Ⅱ 和 闭包 一丶内置函数Ⅱ ####内置函数#### 特别重要,反复练习 ###print() 打印输入 #sep 设定分隔符 # end 默认是换行可以打印到 ...
随机推荐
- sgu 176 有源汇有上下界的最小流模板题
/*参考博文:http://hi.baidu.com/dragon_eric123/item/82e259200ece744046996282 有上下界的有源最小流 */ #include<st ...
- python初码
第一次用python写代码,有一些不习惯,比如if.else.for.def后要加:.假设换一个编译工具可能会好点,否则仅仅能每次执行的时候查看错误信息.它的优点也正是这里不须要每条语句输入;.不须要 ...
- [ACM] POJ 1942 Paths on a Grid (组合)
Paths on a Grid Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 21297 Accepted: 5212 ...
- zoj 1648 Circuit Board
题目:意思就是推断给定的几条线段是否有相交的. 方法:模版吧,有空在来细细学习. 代码: #include <iostream> #include <cstdio> using ...
- Hadoop Web项目--Mahout0.10 MR算法集锦
1. 涉及技术及下载 项目开发使用到的软件有:Myeclipse2014,JDK1.8.Hadoop2.6,MySQL5.6.EasyUI1.3.6,jQuery2.0,Spring4.1.3,Hib ...
- job调度时间格式
*/5 * * * * ?---------------每隔5秒执行一次0 */1 * * * ?---------------每隔1分钟执行一次0 0 23 * * ?--------------- ...
- luogu1312 Mayan游戏 剪枝
题目大意 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个77 行\times 5×5列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游 ...
- Spark之MLlib
目录 Part VI. Advanced Analytics and Machine Learning Advanced Analytics and Machine Learning Overview ...
- RabbltMQ
协议:AMQP协议 支持事务 端口号:默认端口5672 1.简单队列(simple queue) 一个生产者对应一个消费者 2.工作队列(work queue) 一个生产者对应多个消费者: 轮询分发 ...
- Blender插件初始化范例
目标 [x] 总结Blender插件初始化范例 总结 插件模板 Blender内部插件实现方式模板功能总结如下: 定义了子模块重加载方式 定义了批量加载子模块的方式 插件注册函数 插件注销函数 模块总 ...