一篇文章让你明白python的装饰器
在看闭包问题之前先来看看关于python中作用域的问题
变量作用域

对于上述代码中出现错误,肯定没什么疑问了,毕竟b并没有定义和赋值,当我们把代码更改如下后:

再看一个例子:

首先这个错误已经非常明显:说在赋值之前引用了局部变量b
可能很多人觉得会打印10然后打印6,其实这里就是涉及到变量作用域的问题
当Python编译函数的的定义体的时候,它判断b是局部变量,毕竟在函数中有b = 9表示给b赋值了,所以python会从本地环境获取b,当我们调用方法执行的时候,定义体会获取并打印变量a的值,但是当尝试获取b的值的时候发现b没有绑定值,所以要想让上述代码运行还可以把b设置为全局变量,或者把b赋值放到调用之前


函数对象的作用域
python中一切皆对象,同其他对象一样,函数对象也有其使用的范围即函数对象的作用域。
在python中我们通过def定义函数,函数对象的作用域与def所在的层级相同,
通过下面代码进行理解:
def func1():
def func2(x):
return 2*x
print(func2(5)) func1()
print(func2(5))
这个例子中我们在def func1函数内可以调用fun2,但是我们在外面是无法调用到func2的,所以结果为看到如下:

闭包
关于闭包主要有下面两种说法:
- 闭包是符合一定条件的函数,定义为:闭包是在其词法上下文中引用了自由变量的函数
- 闭包是由函数与其相关的引用环境组合而成的实体。定义为:在实现绑定时,需要创建一个能显示表示引用环境的东西,并将它与相关的子程序捆绑在一起,这样捆绑起来的整体称为闭包
个人觉得第二种说法更准确,闭包只是在形式上表现像函数,实际不是函数。
我们对函数的定义是:一些可执行的代码,这些代码在函数定义后就确定了,不会在执行时发生变化,所以一个函数只有一个实例。
闭包在运行的时候可以有多个实例,不同的引用环境和相同的环境组合可以产生不同的实例。
这里有一个词:引用环境,其实引用环境就是在执行运行的某个时间点,所有处于活跃状态的变量所组成的集合,这里的变量是指变量的名字和其所代表的对象之间的联系。
可以使用闭包语言的特点:
- 函数可以作为另外一个函数的返回值或者参数,还可以作为一个变量的值。
- 函数可以嵌套使用
而认为闭包是函数的有一句话是:
闭包是指延伸了作用域的函数,其中包含函数定义体中引用。但是不在定义体中定义的非全局变量。
上面这种说法个人觉得也是一种理解方式
相信看了这些概念也还是不好理解,还是通过下面例子更好理解:
先实现一种计算平均值的方法:

从结果我们可以看出这里保存了每次的历史值
换一种方法实现:

实现了第一种相同的效果,对这种方法分析:
通常我们会认为我们调用avg(10)的时候make_averager函数已经返回了,而它的本地作用域也一去不复返,但这里其实series是自由变量,是指未在本地作用域绑定的变量
我们可以通过print(dir(avg)),看到如下结果:

其实这里面保存着均布变量和自由变量的名称,我们可以通过下面方法查看:

eries的绑定在返回的avg函数的__closure__属性中这或许就是有的人会认为闭包一种函数。闭包会保留定义函数时存在的自由变量的绑定,这样调用函数时虽然定义作用域不能用了,但是仍能使用那些绑定
关于nonlocal
刚开始了解闭包之后,如果尝试使用这种编程方式容易出现以下错误使用例子:
def make_averager():
count = 0
total = 0 def averager(new_value):
count += 1
total += new_value
return total / count
return averager
先来看一下错误提示:

这个例子中和我们上面使用的不同之处是:这里的count和total是数字,是不可变类型,而之前的例子中series是一个列表是可变类型
所以这里重新回到了最开始说的作用域问题了,当我们在averager中使用
count += 1的时候其实就是count = count + 1,这样就是在averager函数定义体中对count进行赋值,count就变成了局部变量。
问题小结:当时数字,字符串,元组等不可变类型时,只能读取不能更新,如果使用类似count += 1就会隐式的把count变成局部变量,所以开始例子中使用series,我们后面的操作是append并且列表还是可变对象
不过python3引入了一个新的关键词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
到这里装饰器的前奏就说完了,下面就是装饰器,我个人觉得装饰器只是闭包的一种应用,闭包在很多情况下都是一种非常好的变成技巧
装饰器
关于装饰器本来是想重新整理一下,看了自己之前整理的博客,已经挺详细的,就把连接直接放这里了
http://www.pythonsite.com/?p=113
一篇文章让你明白python的装饰器的更多相关文章
- 一篇文章教会你利用Python网络爬虫获取电影天堂视频下载链接
[一.项目背景] 相信大家都有一种头疼的体验,要下载电影特别费劲,对吧?要一部一部的下载,而且不能直观的知道最近电影更新的状态. 今天小编以电影天堂为例,带大家更直观的去看自己喜欢的电影,并且下载下来 ...
- 【转】详解Python的装饰器
原文链接:http://python.jobbole.com/86717/ Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现 ...
- 理解Python中的装饰器//这篇文章将python的装饰器来龙去脉说的很清楚,故转过来存档
转自:http://www.cnblogs.com/rollenholt/archive/2012/05/02/2479833.html 这篇文章将python的装饰器来龙去脉说的很清楚,故转过来存档 ...
- 详解Python的装饰器
Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现了say_hello()和say_goodbye()两个函数. def sa ...
- 【转】Python之装饰器
[转]Python之装饰器 本节内容 必要知识回顾 情景模拟 装饰器的概念及实现原理 回马枪(带参数的装饰器) 一. 必要知识回顾 在开始说装饰器之前,需要大家熟悉之前说过的相关知识点: 函数即“变量 ...
- 进阶Python:装饰器 全面详解
进阶Python:装饰器 前言 前段时间我发了一篇讲解Python调试工具PySnooper的文章,在那篇文章开始一部分我简单的介绍了一下装饰器,文章发出之后有几位同学说"终于了解装饰器的用 ...
- 我终于弄懂了Python的装饰器(四)
此系列文档: 1. 我终于弄懂了Python的装饰器(一) 2. 我终于弄懂了Python的装饰器(二) 3. 我终于弄懂了Python的装饰器(三) 4. 我终于弄懂了Python的装饰器(四) 四 ...
- Python各式装饰器
Python装饰器,分两部分,一是装饰器本身的定义,一是被装饰器对象的定义. 一.函数式装饰器:装饰器本身是一个函数. 1.装饰函数:被装饰对象是一个函数 [1]装饰器无参数: a.被装饰对象无参数: ...
- Python札记 -- 装饰器补充
本随笔是对Python札记 -- 装饰器的一些补充. 使用装饰器的时候,被装饰函数的一些属性会丢失,比如如下代码: #!/usr/bin/env python def deco(func): def ...
随机推荐
- 将本地代码上传到github
准备工作上传本地代码到github 准备工作 在github上创建自己的Repository. 安装git,centos的git安装教程. 上传本地代码到github git init git add ...
- 项目常见函数封装,基于Jquery
/// <reference path="jquery-1.8.0.min.js" /> /* * DIV或元素居中 * @return */ jQuery.fn.mC ...
- Recall(召回率)and Precision(精确率)
◆版权声明:本文出自胖喵~的博客,转载必须注明出处. 转载请注明出处:http://www.cnblogs.com/by-dream/p/7668501.html 前言 机器学习中经过听到" ...
- 深圳--博雅互动 Android面试打酱油归来
公司在TCL工业园E4,坐地到西丽站,那边在修路,不好走.B796公交站台在A出口的反方向,还要顺着施工的屏障打个弯,在西丽法院1上车.公司那边比较偏了,附近只有两趟公交.办公地点在10楼,出电梯就可 ...
- iOS代码处理横屏问题
借助通知来控制界面的横竖屏切换.还是整个App中大部分界面都是竖屏,某个界面可以横竖屏切换的情况. 首先,在[General]-->[Device Orientation]设置仅支持竖屏,lik ...
- Extjs6(七)——增删查改之删除
本文基于ext-6.0.0 页面就是前面写的那个,有不清楚的可以看一下前面写页面那篇. 一.在toolbar加一个删除按钮 { text:'删除', iconCls:'x-fa fa-times', ...
- pm2部署多个nodejs项目配置教程
实际项目部署中,我们服务器在启动的时候需要自动启动node服务.以前是通过liunx自带的命令启动.但是随着后台微服务越来越多.每次发布新程序.修改脚本太麻烦了.于是换成PM2来做. 1.首先安装pm ...
- Linux文件系统的层级结构
Linux文件系统的层级结构 文件结构 倒置的树状结构 :Linux的哲学思想是一切皆文件,把几乎所有资源统统抽象为文件形式:包括硬件设备,甚至通信接口等 根目录 :linux的文件起始均从唯一的 ...
- Taffy自动化测试框架简介
Taffy Taffy是基于nosetests的自动化测试框架. Taffy主要用来测试后台服务(包括且不限于Http, Dubbo/hessian, Webservice, Socket等类型接口) ...
- Integrates Git with Sublime 3 to pull or push to Github by using Sublime plugin Git
1. Git must be installed, Sublime plugin "Git" only connects Sublime with Git. Download UR ...