Python 变量作用域,闭包和装饰器
- from dis import dis
- b = 6
- def f1(a):
- print(a)print(b)
- b = 9
- f1(3)
- print(dis(f1)) # dis模块可以查看python函数字节码
解决报错的方案一:申明b全局变量
- from dis import dis
- b = 6
- def f1(a):
- print(a)
- global b
- print(b)
- b = 9
- f1(3)
- print(dis(f1)) # dis模块可以查看python函数字节码
闭包
计算移动平均值
- class Averager:
- def __init__(self):
- self.series = []
- def __call__(self, new_value):
- self.series.append(new_value)
- total = sum(self.series) # 汇总
- return total/len(self.series) # 求平均值
- avg = Averager()
- print(avg(10))
- print(avg(11))
- print(avg(12))
通过高阶函数实现
- def make_averager():
- series = []
- def averager(new_value):
- series.append(new_value)
- total = sum(series)
- return total/len(series)
- return averager
- avg = make_averager()
- print(avg(10))
- print(avg(11))
- print(avg(12))
- print(avg.__code__.co_varnames) # 打印局部变量
- print(avg.__code__.co_freevars) # 打印自由变量
- print(avg.__closure__) # series的绑定在返回的函数的__closure__属性中
- print(avg.__closure__[0].cell_contents) # 这些元素是cell对象,有个cell_contents属性,保存着真正的值
- # 综上,闭包是一种函数,它会保留定义函数时存在的自由变量的绑定,这样调用函数时,虽然定义作用域不可用了,但是仍能使用那些绑定
- # 注意,只有嵌套在其他函数中的函数才可能需要处理不在全局作用域中的外部变量
如果是赋值操作呢?
- def make_averager():
- count = 0
- total = 0
- def averager(new_value):
- count += 1
- total +=new_value
- return total / count
- return averager
- # 这里直接执行会报错,因为count += 1 相当于count = count + 1,因此当在averager的定义体内为count赋值,会把count变成局部变量。total变量也是同理
解决方案
- # 引入nonlocal声明,作用是把变量标记为自由变量
- def make_averager():
- count = 0
- total = 0
- def averager(new_value):
- nonlocal count, total
- count += 1
- total += new_value
- return total / count
- return averager
装饰器代码一
- def deco(func):
- def inner(*args, **kwargs):
- print('this is inner')
- return inner
- @deco
- def foo():
- print('this is foo')
- foo() # this is inner
- print(foo.__name__) # inner
装饰器代码二
- def wrap(func):
- def deco(*args, **kwargs):
- print('deco ==> ', args, kwargs)
- func(*args, **kwargs)
- print('this is inner')
- return deco
- @wrap
- def foo(*args, **kwargs):
- print('this is foo')
- foo()
- # deco ==> () {}
- # this is foo
- # this is inner
- print(foo.__name__) # deco
装饰器代码三
- from functools import wraps
- def wrap(func):
- @wraps(func)
- def deco(*args, **kwargs):
- print('deco ==> ', args, kwargs)
- func(*args, **kwargs)
- print('this is inner')
- return deco
- @wrap
- def foo(*args, **kwargs):
- print('this is foo')
- foo()
- # deco ==> () {}
- # this is foo
- # this is inner
- print(foo.__name__) # foo
有空讲解0.0
Python 变量作用域,闭包和装饰器的更多相关文章
- 21.python中的闭包和装饰器
python中的闭包从表现形式上定义(解释)为:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure). 以下说明主要针对 python ...
- Python 中的闭包与装饰器
闭包(closure)是函数式编程的重要的语法结构.闭包也是一种组织代码的结构,它同样提高了代码的可重复使用性. 如果在一个内嵌函数里,对在外部函数内(但不是在全局作用域)的变量进行引用,那么内嵌函数 ...
- python中的闭包和装饰器
重新学习完了函数,是时候将其中的一些重点重新捋一捋了,本次总结的东西只有闭包和装饰器 1.闭包 闭包是python函数中的一个比较重要功能,一般闭包都是用在装饰器上,一般学完闭包就会去学习装饰器,这俩 ...
- 【Python 函数对象 命名空间与作用域 闭包函数 装饰器 迭代器 内置函数】
一.函数对象 函数(Function)作为程序语言中不可或缺的一部分,但函数作为第一类对象(First-Class Object)却是 Python 函数的一大特性. 那到底什么是第一类对象(Firs ...
- Python作用域-->闭包函数-->装饰器
1.作用域: 在python中,作用域分为两种:全局作用域和局部作用域. 全局作用域是定义在文件级别的变量,函数名.而局部作用域,则是定义函数内部. 关于作用域,我要理解两点:a.在全局不能访问到局部 ...
- Python记录9:函数4:名称空间作用域+闭包函数+装饰器
''' 一: 名称空间namespaces 名称空间就是存放名字与值绑定关系的内存空间 二: 名称空间分为三种 内置名称空间: 1. 特点: 存放是python解释器自 ...
- 第十七篇 Python函数之闭包与装饰器
一. 装饰器 装饰器:可以拆解来看,器本质就是函数,装饰就是修饰的意思,所以装饰器的功能就是为其他函数添加附加功能. 装饰器的两个原则: 1. 不修改被修饰函数的源代码 2. 不修改被修饰函数的调用方 ...
- python 小兵(8)闭包和装饰器
闭包"是什么,以及,更重要的是,写"闭包"有什么用处. (个人理解) 1."闭包"是什么 首先给出闭包函数的必要条件: 闭包函数必须返回一个函数对象 ...
- 轻松理解python中的闭包和装饰器(上)
继面向对象编程之后函数式编程逐渐火起来了,在python中也同样支持函数式编程,我们平时使用的map, reduce, filter等都是函数式编程的例子.在函数式编程中,函数也作为一个变量存在,对应 ...
- python基础16_闭包_装饰器
不了解是否其他语言也有类似 python 装饰器这样的东西. 最近才发现ECMAScript6也是有生成器函数的,也有 yield generator 装饰器的基础知识是闭包: # 闭包:嵌套函数, ...
随机推荐
- java8 list转map,list集合中的元素的属性转set,list集合中对象的属性转list
一.使用java8对list操作 1.1list转map private Map<String, Member> getMemberMap() { List<Member> m ...
- [题解] P2513 [HAOI2009]逆序对数列
动态规划,卡常数 题目地址 设\(F[X][Y]\)代表长度为\(X\)的序列,存在\(Y\)组逆序对的方案数量. 考虑\(F[X][i]\)向\(F[X+1][i]\)转移: 把数字\(X+1\)添 ...
- dump解析入门-用VS解析dump文件进行排障
突然有一天部署在服务器的一个应用挂掉了,没办法只能进入服务器打开 [事件查看器]查看下,好不容易找到了打开后一脸懵逼 事件查看器查到的内容根本对我们排障没有任何作用. 在这个时候如果有对应的dump文 ...
- vue填坑指南之模板的使用
坑提示:"The template root requires exactly one element" Src下面有个App.vue文件,在index里引用了这个文件以后,我在. ...
- 深入Redis持久化
转载:https://segmentfault.com/a/1190000017193732 一.Redis高可用概述 在介绍Redis高可用之前,先说明一下在Redis的语境中高可用的含义. 我们知 ...
- JS学习笔记:(二)回流和重绘
在搞清楚回流和重绘的概念之前,我们要清除浏览器的渲染过程. 解析生成DOM Tree(此时包含所有节点,包括display:none); 根据CSS Object Module(CCSSOM)计算节点 ...
- 初探kafka streams
1.启动zookeeper zkServer.cmd 2.启动kafka kafka-server-start.bat d:\soft\tool\Kafka\kafka_2.12-2.1.0\conf ...
- jsp学习(2)jsp标签
1.脚本程序 脚本程序可以包含任意量的Java语句.变量.方法或表达式,只要它们在脚本语言中是有效的. 脚本程序的语法格式:<%代码片段%>您也可以编写与其等价的XML语句,就像下面这样: ...
- MonkeyRunner 综合实践
综合实践 测试场景 连接设备,自动安装并启动考研帮app 启动后登录账号(账号zxw1234 密码:zxw123456),然后截图并保存到指定文件位置. 思路分析 连接设备 安装app 启动app 输 ...
- MarkdownPad
MarkdownPad Markdown编辑器,只能在windows下使用 下载地址 :http://markdownpad.com/ 破解: 邮箱:Soar360@live.com 授权证书 GBP ...