Python 名称空间与作用域、闭包与装饰器
Python 的名称
Python 的名称(Name)是对象的一个标识(Identifier)。我们知道,在 Python 里面一切皆对象,名称就是用来引用对象的。说得有点玄乎,我们以例子说明。
例如,在a = 2
这个语句中,2
是个存储在内存中的一个对象,名称a
则会引用2
这个对象,“引用”的含义是指可以通过名称a
来使用2
这个对象。我们可以使用id()
函数来获取对象的地址。
可以看到,两都均指向同一个对象
Python 的名称与对象
起初,名称a
引用对象2
;
然后,执行操作a = 1
,这时对象1
被创建,名称a
引用对象1,所以id(a)
和id(1)
输出相同的地址; 但是对象2没有名称引用,继而丢弃在内存空间中成为垃圾。
这个例子也展示了 Python 在执行变量的赋值时,并不会重复创建一个对象的事实。名称采用动态绑定的机制使得 Python 更加高效,同一个名称可以引用不同类型的对象。
Python 的名称空间
名称空间是名称到对象的映射。在 Python 中,名称空间采用字典来实现。Python 的名称空间包括:
- 内置名称空间,例如,内置名称空间包含 Python 的内置函数,如,
abs()
- 模块名称空间,全局名称空间,在模块内定义的名称
- 局部名称空间,例如,在函数(function)或者类(class)被调用时,其内部包含的名称
不同的名称空间内的名称不会相互冲突,即是它们采用相同的名称。这也正是名称空间的作用。
内置名称空间在 Python 解释器启动时就创建了,直到 Python 解释器退出时内置名称空间才失效。这使得我们可以在程序的任何位置使用内置名称空间内的名称,例如,id()
,print()
等函数。
模块名称空间当模块被引用时创建,直到 Python 解释器退出时模块名称空间才失效。
函数名称空间在函数被调用时创建,函数返回后失效。
Python 变量的作用域
例子
在这个例子中,名称a
在全局名称空间中,名称b
在函数outer_function
的局部名称空间,名称c
则在函数inner_func
的局部名称空间。
当我们在函数inner_func
时,c
是个局部的名称,b
是个非局部的名称,而a
则是个全局的名称。在函数inner_func
中,我们可以对c
进行读取操作和赋值操作,而只能对b
和a
进行读取操作。当对b
进行赋值时,一个新的名称将会被创建,这个新的名称处于inner_func
函数局部名称空间中。对a
进行赋值时也会在局部名称空间中创建一个新的名称。
如果想要对全局变量进行修改以便下次调用,可以用global xxx(变量名)即可。
Python 闭包
如果在一个函数的内部定义了另一个函数,外部的我们叫他外函数,内部的我们叫他内函数。
在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。
在python3中,可以用nonlocal 关键字声明 一个变量, 表示这个变量不是局部变量空间的变量,需要向上一层变量空间找这个变量。
闭包有啥用??!!
装饰器!!!装饰器是做什么的??其中一个应用就是,我们工作中写了一个基础平台功能,我们想让别的部门可以调用,但是原先基础平台又不允许改代码,这就是装饰器的作用
面向对象!!!经历了上面的分析,我们发现外函数的临时变量送给了内函数。大家回想一下类对象的情况,对象有好多类似的属性和方法,所以我们创建类,用类创建出来的对象都具有相同的属性方法。闭包也是实现面向对象的方法之一。在python当中虽然我们不这样用,在其他编程语言入比如avaScript中,经常用闭包来实现面向对象编程
实现单利模式!! 其实这也是装饰器的应用。单利模式毕竟比较高大,,需要有一定项目经验才能理解单利模式到底是干啥用的,我们就不探讨了。
Python 装饰器
当写完这段代码后(函数未被执行、未被执行、未被执行),python解释器就会从上到下解释代码,步骤如下:
- def w1(func): ==>将w1函数加载到内存
- @w1
- @w1就相当于 #下面定义的函数名 = w1(定义的函数名作为实参),当最下面一行 调用 f1()的函数的时候才是会去闭包里的inner函数执行相应的操作
没错,从表面上看解释器仅仅会解释这两句代码,因为函数在没有被调用之前其内部代码不会被执行。
从表面上看解释器着实会执行这两句,但是 @w1 这一句代码里却有大文章,@函数名 是python的一种语法糖。
如上例@w1内部会执行一下操作:
- 执行w1函数,并将 @w1 下面的 函数 作为w1函数的参数,即:@w1 等价于 w1(f1)
所以,内部就会去执行:
def inner:
return f1() # func是参数,此时 func 等于 f1
return inner # 返回的 inner,inner代表的是函数,非执行函数
其实就是将原来的 f1 函数塞进另外一个函数中 - 将执行完的 w1 函数返回值赋值给@w1下面的函数的函数名
w1函数的返回值是:
def inner:
return 原来f1() # 此处的 f1 表示原来的f1函数
然后,将此返回值再重新赋值给 f1,即:
新f1 = def inner:
return 原来f1()
所以,以后业务部门想要执行 f1 函数时,就会执行 新f1 函数,在 新f1 函数内部先执行验证,再执行原来的f1函数,然后将 原来f1 函数的返回值 返回给了业务调用者。
如此一来, 即执行了验证的功能,又执行了原来f1函数的内容,并将原f1函数返回值 返回给业务调用着
Python 名称空间与作用域、闭包与装饰器的更多相关文章
- python名称空间和作用域
python名称空间和作用域 名称空间 名称空间:例如a=1000,python解释器会开辟一块新的内存来存贮1000这个变量值,然后会有一个a指向这个1000,那么a存在哪里?其实他和变量值差不多, ...
- Python记录9:函数4:名称空间作用域+闭包函数+装饰器
''' 一: 名称空间namespaces 名称空间就是存放名字与值绑定关系的内存空间 二: 名称空间分为三种 内置名称空间: 1. 特点: 存放是python解释器自 ...
- Python 函数对象-函数嵌套-名称空间与作用域-闭包函数
今日内容: 1. 函数对象 函数是第一类对象: 指的是函数名指向的值可以被当中数据去使用 1.可以被引用 2.可以当做参数传给另一个函数 3.可以当做一个函数的返回值 4.可以当做容器类型的元素 2. ...
- Python名称空间与作用域
什么是名称空间? 比如下图的长方形代表内存,在这个内存里我要设置一个变量100,那么这个变量得有个门牌号,就叫他a吧,但其实变量不是这么存储的,他其实的存储方式是这样的,他会有一个名称空间,这个名称空 ...
- Python 名称空间和作用域
a = 10 # lst = [1,2,3,4] # # # 内置函数 print("你好啊,我叫赛利亚") # def chi(): a = 10 b = 20 # # # # ...
- 13、python中的函数(闭包与装饰器)
一.嵌套函数 函数的内部又再定义另一个函数,这个函数就叫嵌套函数,里面含函数就叫内部函数. 示例: 二.返回函数 函数可以接收函数对象作为参数,同理函数也能返回一个函数对象作为返回值. 示例: 返回函 ...
- python 生成器,迭代器,闭包,装饰器
1.生成器,迭代器,闭包,装饰器的优点 生成器就是一类特殊的迭代器 迭代器的优点也即生成器的优点: 1.节约内存.python在使用生成器时对延迟操作提供了支持. 2.迭代到下一次的调用时,所使用的参 ...
- Python的高级特性7:闭包和装饰器
本节跟第三节关系密切,最好放在一起来看:python的高级特性3:神奇的__call__与返回函数 一.闭包:闭包不好解释,只能先看下面这个例子: In [23]: def outer(part1): ...
- 【Python 函数对象 命名空间与作用域 闭包函数 装饰器 迭代器 内置函数】
一.函数对象 函数(Function)作为程序语言中不可或缺的一部分,但函数作为第一类对象(First-Class Object)却是 Python 函数的一大特性. 那到底什么是第一类对象(Firs ...
随机推荐
- java中Keytool的使用总结 (加密 密钥(key)和证书(certificates))
http://blog.chinaunix.net/uid-17102734-id-2830223.html
- SQL Server 2008 允许远程链接 解决方法
用户在使用SQL Server 2008远程链接时,可能会弹出如下对话框: 在链接SQL服务器时发生网络链接错误或特定实例错误.SQL服务器不存在或者链接不成功.请验证用户名是否正确或SQL服务器是否 ...
- 服务器端cs文件
服务器端向mysql数据库写数据 using System; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System.Colle ...
- input 和<fmt:formatDate>的结合使用
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <inpu ...
- yield return关键字怎么使用?
在迭代器块中用于向枚举数对象提供值或发出迭代结束信号.它的形式为下列之一: 复制代码 yield return <expression>;yield break; 备注计算表达式并以枚举数 ...
- Python高级编程之生成器(Generator)与coroutine(二):coroutine介绍
原创作品,转载请注明出处:点我 上一篇文章Python高级编程之生成器(Generator)与coroutine(一):Generator中,我们介绍了什么是Generator,以及写了几个使用Gen ...
- Redis-stat is not found
$ruby -v ruby 2.1.3p242 (2014-09-19 revision 47630) [x86_64-linux] $gem -v 2.2.2 $which ruby /usr/lo ...
- SQL之Join的使用
一.基本概念 关于sql语句中的连接(join)关键字,是较为常用而又不太容易理解的关键字,下面这个例子给出了一个简单的解释 –建表user1,user2: table1 : create table ...
- ulimit命令学习
通过ulimit -n命令可以查看linux系统里打开文件描述符的最大值,一般缺省值是1024,对一台繁忙的服务器来说,这个值偏小,所以有必要重新设置linux系统里打开文件描述符的最大值.那么应该在 ...
- ztree获取选中节点时不能进入可视区域出现BUG如何解决
zTree 是一个依靠 jQuery 实现的多功能 “树插件”.优异的性能.灵活的配置.多种功能的组合是 zTree 最大优点. zTree 的特点编辑 ● zTree v3.0 将核心代码按照功能进 ...