第一部分

最近在写Python的时候发现一个好玩的现象,就是在if else重定义的变量,没有声明全局,在外部也可以使用,

这里涉及到一个python变量生命周期的问题。

python能够改变变量作用域的代码段是def、class、lamda.

if/elif/else、try/except/finally、for/while 并不能涉及变量作用域的更改,

也就是说他们的代码块中的变量,在外部也是可以访问的

变量搜索路径是:本地变量->全局变量

https://img-blog.csdn.net/20161110105647895?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

http://blog.csdn.net/u012965373/article/details/53113586

第二部分

python中,对于变量作用域的规定有些不一样。在诸如C/C++、java等编程语言中,默认在函数的内部是可以直接访问在函数外定义的全局变量的,但是这一点在python中就会有问题,下面是一个例子。

test.py:

#!/usr/bin/python

COUNT=1

def func():

COUNT = COUNT + +1

func()

Python test.py,会运行报错:

Traceback (most recent call last):

File "test.py", line 8, in

func()

File "test.py", line 6, in func

COUNT = COUNT + +1

UnboundLocalError: local variable 'COUNT' referenced before assignment

“UnboundLocalError: local variable 'COUNT' referenced before assignment”的意思是变量COUNT在赋值之前被引用。

这里要知道python和其它编程语言不一样的地方。像C/C++之类的编程语言,变量名称实际上是代表的一块内存区域,对该变量赋值的意思就是将新的值放入该变量指定的内存区域。而对于python来说,所有的变量都是对内存区域的引用,对变量赋值相当于将变量引用的内存从一块区域改变到另外一块存放新值的区域。也就是说,C/C++中,变量名和内存区域的对应关系不会变,变的只是对应内存中存放的值;而在python中,变量只是对存放其值的内存区域的引用,变量值的改变不是因为变量指向的内存区域中的值发生了变化,而是变量引用了新的存放新值的内存区域。python中的所有变量都是相当于java中的不可变的变量,任何一次值的改变都对应着变量引用内存区域的变化。区别如下图1:

图1 变量的比较

python中有一个id函数,python中有一个id函数,help(id)可以看到它的说明,如下:

Help on built-in function id in module __builtin__:

id(...)

id(object) -> integer

Return the identity of an object. This is guaranteed to be unique among simultaneously existing objects.(Hint: it's the object's memory address.)

(END)

简单地说,id函数反应的是对象的内存地址,看下面的实验结果:

test.py:

#!/usr/bin/python

COUNT = 1

for i in range(5):

COUNT = COUNT + 1

print id(COUNT)

python test.py运行结果:

11031328

11031304

11031280

11031256

11031232

这里和上面图上说明的相吻合,python中每一次赋值都使变量引用的内存空间发生了改变。

回到上面“referenced before assignment”的错误,之所以会发生这种错误是因为python在函数中发现对于COUNT变量的赋值,会将其添加到函数的局部命名空间(实际上,这是在函数运行到赋值操作之前发生的)。进行赋值操作时,赋值操作符的右边引用了COUNT变量,而这时COUNT变量只是被添加到了函数的局部命名空间,而没有被具体赋值,所以会发生上面的错误。实际上,这里问题就出在赋值操作的地方,因为有赋值操作导致该变量被添加到了函数的局部命名空间。如果没有赋值,只是引用该变量,是没有什么问题的,如下:

test.py:

#!/usr/bin/python

COUNT=1

def func():

temp = COUNT + 1

print "temp:",COUNT

print "COUNT:",COUNT

func()

python test.py运行结果:

temp: 1

COUNT: 1

这样,COUNT变量没有被添加到函数的局部命名空间,python解释器在函数的局部命名空间中没有查找到它,然后,python解释器会继续在全局的命名空间中查找,结果在全局命名空间中找到COUNT的定义并引用它的值,所以程序运行没有任何问题。

到这里你可能会问,难道在函数中没法修改全局变量的值吗?不是的,如果要在函数中修改全局变量的值,就要在函数中对该变量进行global声明,以告诉python解释器,该变量是全局命名空间中的,如下:

test.py:

#!/usr/bin/python

COUNT=1

def func():

global COUNT

COUNT = COUNT + 1

print "COUNT:",COUNT

func()

python test.py运行结果:

COUNT: 2

python变量生命周期_python 变量定义及变量生命周期相关推荐

  1. python整型变量的使用_python(二)数据类型与变量

    python基础之数据类型与变量 一.变量 变量 声明变量 #!/usr/bin/env python age=18 gender1='male' gender2='female' 变量作用:保存状态 ...

  2. python函数的定义域_python中多线程的变量定义域问题

    最近遇到了一个还算常见的错误提示:local variable 'xxx' referenced before assignment 字面上的意思就是该变量在引用前还未定义,于是我去代码里找到了这个变 ...

  3. python交换两个变量的值_python交换两个变量的值方法

    python交换两个变量的值方法 大部分语言,例如c语言,交换两个变量的值需要使用中间变量. 例如交换a,b 伪代码: tmp = a a = b b = tmp python里面可以实现无临时变量的 ...

  4. python保存变量到本地_python小技巧——将变量保存在本地及读取

    在用jupyter notebook写python代码的过程中会产生很多变量,而关闭后或者restart jupyter kernel后所有变量均会消失,想要查看变量就必须将代码重新再运行一遍,而想在 ...

  5. python变量类型声明_python中可以声明变量类型吗

    变量(variable)是Python语言中一个非常重要的概念.变量的主要作用就是为Python程序中的某个值起一个名字.类似于"张三"."李四"." ...

  6. python变量类型声明_python基础知识:变量的定义以及类型

    本文适合编程语言零基础的初学者,有打算转行学习python的可以添加关注,后续小编将会把自己转行学pyhton语言以来的所有笔记,和工作中总结的一些开发经验分享给大家. 变量的定义 在程序中,有时我们 ...

  7. python转r字符_python r不转义变量

    普通字符串常量 含有转义字符,会按照转义字符的意义输出,如下:text="1 E:/Code/PycharmProjects/QtDemo/ToolsList\__pycache__\sta ...

  8. python怎么交换两个变量的值_python交换两个变量的值方法

    大部分语言,例如c语言,交换两个变量的值需要使用中间变量. 例如交换a,b 伪代码: tmp = a a = b b = tmp python里面可以实现无临时变量的交换 (a,b) = (b,a) ...

  9. python的字符串类型_python如何判断某变量是否为字符串类型

    isinstance是Python中的一个内建函数 语法:isinstance(object, classinfo) 如果参数object是classinfo的实例,或者object是classinf ...

  10. python类属性初始化_Python类定义、属性、初始化和析构

    类的定义,属性和方法概念 方法中self的作用和意义 初始化( __init__ ) 和 析构方法( __del__ ) 类的定义 class 类名 实例 实例名 = 类名() 一个"实例& ...

最新文章

  1. java redis管理_优雅时间管理Java轻松做到,想学么?
  2. 一篇深入剖析PCA的好文
  3. python字符串换行连接_零基础学python_03_字符串(拼接+换行+制表符)
  4. [渝粤教育] 中国地质大学 金融保险业会计 复习题
  5. centos6.4 卸载mysql_彻底删除MYSQL-CENTOS
  6. [html] 写页面布局时你有考虑过分辨率因素吗?还要考虑哪些因素呢
  7. python中字符集
  8. 【nand2tetris实验0】windows找不到文件javaw的解决办法
  9. c语言构成循环结构的是,C语言循环结构选择题
  10. IDEA中java文件的左下角有个像乐符一样的J符号
  11. 从一个程序看继承的有关细节及规则(学习马士兵视频的总结)
  12. 白杨SEO:SEM和SEO有什么区别呢?
  13. amos调节变量怎么画_结构方程模型建模思路及Amos操作--调节变量效果确定(二)...
  14. switch语句应用例题
  15. 选择什么语言真的重要吗
  16. 腾达便携无线路由 无法建立到192.168.2.1的服务器连接,Tenda腾达路由器5G信号设置步骤...
  17. Oracle EBS FSG报表输出记录追溯出错
  18. LaTeX插入矩阵和方程组
  19. 使用python库relate搭建LMS学习管理系统
  20. springboot入门

热门文章

  1. iOS开发那些悲剧的事儿
  2. VS或编译的时候不生成Release文件夹
  3. 电大计算机网考选择题多少分,2016年度电大计算机网考选择题及标准答案.doc
  4. linux组类型,LINUX用户以及用户组
  5. java统计报表日期工具类
  6. JMeter场景设置与监控
  7. jmeter模拟http请求/发送gzip数据
  8. html不支持元素video,Html5中的Video元素使用方法
  9. java socat_socat安装使用方法
  10. 泰拉瑞亚服务器怎么让玩家注册,上线10年,《泰拉瑞亚》为何变成了一款交友游戏?...