先看一个问题:

  下面代码输出的结果是0,换句话说,这个fucn2虽然已经用global声明了variable1,但还是没有改变变量的值

  1. def func1():
  2. variable1=0
  3. def func2():
  4. global variable1
  5. variable1=2
  6. func2()
  7. print(variable1)
  8. if __name__=="__main__":
  9. func1()
  10.  
  11. #下面这段代码也是输出0
  12. variable1=0
  13. def func1():
  14. variable1=0
  15. def func2():
  16. global variable1
  17. variable1=2
  18. func2()
  19. print(variable1)
  20. if __name__=="__main__":
  21. func1()

  下面代码的输出结果是2,这个global起作用了

  1. variable1=0
  2. def func1():
  3. # variable1=0
  4. def func2():
  5. global variable1
  6. variable1=2
  7. func2()
  8. print(variable1)
  9. if __name__=="__main__":
  10. func1()

  

变量作用域涉及到的知识:

参考链接:https://www.jianshu.com/p/3bb277c2935c

    python中变量作用域的分类:

  python中的变量作用域一共有四种

  • 局部作用域(L:Local)

局部变量是指在函数内部定义并使用的变量,它只在函数内部有效。离开函数之后就不能再访问局部变量了,否则解释器会抛出 NameError 错误。

  • 闭包函数外的函数中(E:Enclosing)

闭包的定义:如果在一个内部函数里,对在外部函数内(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)

  • 全局作用域(G:Global)

和局部变量相对应,全局变量指的是能作用于函数内外的变量,即全局变量既可以在各个函数的外部使用,也可以在各函数内部使用。

定义的方式有两种:在函数体外定义的变量,一定是全局变量;在函数体内定义全局变量。即使用 global 关键字对变量进行修饰后,该变量就会变为全局变量。

  • 内建作用域(B:Built-in)

变量作用域中的一些规则

  在不同的变量作用域中查找变量的顺序

  以 L --> E --> G -->B 的规则查找,即:在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内建中找。

  所以python中对变量的命名没有关键字冲突,但是会出现这样的情况,在重复的变量的作用域中

  1. >>> str(2)
  2. '2'
  3. >>> str=5
  4. >>> str
  5. 5
  6. >>> str(2)
  7. Traceback (most recent call last):
  8. File "<stdin>", line 1, in <module>
  9. TypeError: 'int' object is not callable
  10. >>>

  

  另外这样的查找顺序还可能会带来另一个问题:全局变量和局部变量的遮蔽现象(同名的时候喽)

  全局变量默认可以在所有函数内被访问,但如果在函数中定义了与全局变量同名的变量,此时就会发生局部变量遮蔽(hide)全局变量的情形

  1. var = 1
  2. def fun():
  3. print var
  4. var = 200
  5. print fun()
  6.  
  7. #file2.py
  8. var = 1
  9. def fun():
  10. var = var + 1
  11. return var
  12. print fun()
  13. # 这两个函数都会报错UnboundLocalError: local variable 'var' referenced before assignment

  因为在函数的内部,解释器探测到var被重新赋值了,所以var成为了局部变量,但是在没有被赋值之前就想使用var,便会出现这个错误。解决的方法是在函数内部添加 globals var 但运行函数后全局的var也会被修改。

  python能够改变变量作用域的代码段是def、class、lamda.其他如: if/elif/else/ try/except for/while并不能改变其作用域。定义在他们之内的变量,外部还是可以访问。

  1. >>> if True:
  2. ... a = 'I am A'
  3. ...
  4. >>> a
  5. 'I am A'
  6. # 定义在if语言中的变量a,外部还是可以访问的。
  7. # 但是需要注意如果if被 def/class/lambda 包裹,在内部赋值,就变成了此 函数/类/lambda 的局部作用域。

  在 def/class/lambda内进行赋值,就变成了其局部的作用域,局部作用域会覆盖全局作用域,但不会影响全局作用域。

闭包

  

  闭包的定义:如果在一个内部函数里,对在外部函数内(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)

  在最开始的问题中,访问 func1中的variable1的func2就是一个闭包,Python3有个关键字nonlocal可以解决这个问题,但在Python2中还是不要尝试修改闭包中的变量。

  1. def func1():
  2. variable1=0
  3. def func2():
  4. nonlocal variable1#这样就好了
  5. variable1=2
  6. func2()
  7. print(variable1)
  8. if __name__=="__main__":
  9. func1()

  关于闭包中还有一个坑:

  1. from functools import wraps
  2.  
  3. def wrapper(log):
  4. def external(F):
  5. @wraps(F)
  6. def internal(**kw):
  7. if False:
  8. log = 'modified'
  9. print log
  10. return internal
  11. return external
  12.  
  13. @wrapper('first')
  14. def abc():
  15. pass
  16.  
  17. print abc()
    #也会出现nameerror:引用在定义之前

  原因是解释器探测到了 if False 中的重新赋值,根据变量的搜索规则,所以不会去闭包的外部函数(Enclosing)中找变量,但 if Flase 不成立没有执行(所以log赋值就没有执行即没有定义 ),所以便会出现此错误。除非你还需要else: log='var' 或者 if True 但这样添加逻辑语句就没了意义(为什么没有意义呢?),所以尽量不要修改闭包中的变量

  

获取指定作用域范围中的变量

  参考链接:http://c.biancheng.net/view/2259.html

  不管是在函数的局部范围内还是在全局范围内,都可能存在多个变量,每个变量“持有”该变量的值。从这个角度来看,不管是局部范围还是全局范围,这些变量和它们的值就像一个“看不见”的字典,其中变量名就是字典的 key,变量值就是字典的 value。实际上,Python 提供了如下三个工具函数来获取指定范围内的“变量字典”:

  1. globals():该函数返回全局范围内所有变量组成的“变量字典”。
  2. locals():该函数返回当前局部范围内所有变量组成的“变量字典”。
  3. vars(object):获取在指定对象范围内所有变量组成的“变量字典”。如果不传入object 参数,vars() 和 locals() 的作用完全相同。

  

  globals() 和 locals() 看似完全不同,但它们实际上也是有联系的,关于这两个函数的区别和联系大致有以下两点:

  • locals() 总是获取当前局部范围内所有变量组成的“变量字典”,因此,如果在全局范围内(在函数之外)调用 locals() 函数,同样会获取全局范围内所有变量组成的“变量字典”;而 globals() 无论在哪里执行,总是获取全局范围内所有变量组成的“变量字典”。
  • 一般来说,使用 locals() 和 globals() 获取的“变量字典”只应该被访问,不应该被修改。但实际上,不管是使用 globals() 还是使用 locals() 获取的全局范围内的“变量字典”,都可以被修改,而这种修改会真正改变全局变量本身:但通过 locals() 获取的局部范围内的“变量字典”,即使对它修改也不会影响局部变量。

python 变量作用域、闭包的更多相关文章

  1. Python 变量作用域与函数

    Python 的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言的一种继承.Py ...

  2. Python 变量作用域 LEGB (下)—— Enclosing function locals

    上篇:Python 变量作用域 LEGB (上)—— Local,Global,Builtin https://www.cnblogs.com/yvivid/p/python_LEGB_1.html ...

  3. python变量作用域

    [python变量作用域] 几个概念: python能够改变变量作用域的代码段是def.class.lamda. if/elif/else.try/except/finally.for/while 并 ...

  4. Python 变量作用域 LEGB (上)—— Local,Global,Builtin

    Python 变量作用域的规则是 LEGB LEGB含义解释:L —— Local(function):函数内的名字空间E —— Enclosing function locals:外部嵌套函数的名字 ...

  5. python——变量作用域及嵌套作用域

    ----------------------------------------------------------------------------- 前言-------------------- ...

  6. python变量作用域,函数与传参

    一.元组传值: 一般情况下函数传递参数是1对1,这里x,y是2个参数,按道理要传2个参数,如果直接传递元祖,其实是传递一个参数 >>> def show( x, y ): ... p ...

  7. Python 变量作用域,闭包和装饰器

    from dis import dis b = 6 def f1(a): print(a)print(b) b = 9 f1(3) print(dis(f1)) # dis模块可以查看python函数 ...

  8. Python变量作用域(一)

    在一个程序中使用变量名时,Python创建.改变或者查找变量名都是在所谓的命名空间中进行的.作用域指的就是命名空间. Python中的变量名在第一次赋值时已经创建,并且必须经过赋值后才能够使用.由于变 ...

  9. python 变量作用域 v.__sizeof__() python 深复制 一切皆对象 尽量减少内存消耗

    python 深入理解 赋值.引用.拷贝.作用域 - 江召伟 - 博客园 https://www.cnblogs.com/jiangzhaowei/p/5740913.html a=[1,2,5]b= ...

随机推荐

  1. JavaScript实现的图片循环播放

    直接上干货 <html> <head> <title>Banner Cycler</title> <script> var banners ...

  2. Apicloud微信支付iOS可以,安卓返回-1的之避坑指南

    相信各位小伙伴在接入微信支付的时候,一定遇到过返回-1的这个问题,说实话,这个问题真的很恶心,微信开放平台提供的文档在关于-1这个问题的描述(可能的原因:签名错误.未注册APPID.项目设置APPID ...

  3. [TCP/IP] 三次握手过程中有哪些不安全性

    1)SYN flood 泛洪攻击 , 伪装的IP向服务器发送一个SYN请求建立连接,然后服务器向该IP回复SYN和ACK,但是找不到该IP对应的主机,当超时时服务器收不到ACK会重复发送.当大量的攻击 ...

  4. Linux-CentOS-Nginx安装

    原文转自 jerryhe326:https://www.cnblogs.com/jerrypro/p/7062101.html 一.安装准备 首先由于nginx的一些模块依赖一些lib库,所以在安装n ...

  5. 其他综合-Cobbler无人值守安装系统 CentOS 7

    Cobbler 无人值守安装系统 CentOS 7 1.实验描述 1.1 概述 作为运维,在公司经常遇到一些机械性重复工作要做,例如:为新机器装系统,一台两台机器装系统,可以用光盘.U盘等介质安装,1 ...

  6. tensorflow模型量化实例

    1,概述 模型量化应该是现在最容易实现的模型压缩技术,而且也基本上是在移动端部署的模型的毕竟之路.模型量化基本可以分为两种:post training quantizated和quantization ...

  7. HBuilder创建app 基础

    一.了解HBuilder HBuilder内封装了大量的书籍,极大方便了使用 官方文档: http://dev.dcloud.net.cn/mui/ui/ 关于布局: mhead  表头.mbody ...

  8. python 爬虫之-- 正则表达式

    正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配. 正则表达式非python独有,python 提供了正则表达式的接口,re模块 一.正则匹配字符简介 模式 描述 \d ...

  9. 【Spring AOP】通知(五)

    一.通知介绍 1. 前置通知(Before) 在目标方法执行之前执行的通知. 前置通知方法,可以没有参数,也可以额外接收一个JoinPoint,Spring会自动将该对象传入,代表当前的连接点,通过该 ...

  10. 了解html

    什么是html? html:Hyper Text Markup Language(超文本标记语言) 纯文本:只能存储一些简单的字符(不能插入图片.视频...) 注意:html不是一种编程语言(它没有任 ...