python 中使用 global,莫名其妙的问题

哪里出问题了

  python 中,使用 global 会将全局变量设为本函数可用。同时,在函数内部访问变量会先本地再全局

  在嵌套函数中,使用 global 会产生不合常理的行为。

  上代码:

In [96]: def x():
    b = 12
    def y():
        global a,b
        a = 1
        b = 2
    y()
    print "b =",b
   ....:     

In [97]: a = 111

In [98]: del b

In [99]: x()
b = 12

In [100]: a
Out[100]: 1

In [101]: b
Out[101]: 2

  而在函数 x() 中,没有用 global,此时的b使用本地。所以 print 会打印本地 b

  为什么会打印 12 ?还有 In[101]的 b 为 2 该怎么解释?

  

  y(),使用的 global 竟然没把 x() 的 b = 12 导进来。

  在函数 y() 中,语句  global a,b  使a,b扩展为全局,所以,在最高层,就算没有 b(In[98]),也会产生 b(In[101])。

  

  也就是说, global a,b ,会认为 a 和 b 是最外层的变量。

  再试一下:

  

In [102]: def x():
    b = 12
    def y():
        global a,b
        a = 1
    y()
    print "b =",b
   .....:     

In [103]: a = 111

In [104]: del b

In [105]: x()
b = 12

In [106]: a
Out[106]: 1

In [107]: b
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-107-3b5d5c371295> in <module>()
----> 1 b

NameError: name ‘b‘ is not defined

  

  报错了! y() global b 后没赋值,顶层就没有 b。这说明,global 只是引入名称,并不做赋值等操作。

  global 不会管变量存不存在,只导入名称,对该名称的操作会反应到 ‘最高层名称空间‘。

  再来:

  

In [109]: a = 111

In [110]: del b
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-110-745f2abe7045> in <module>()
----> 1 del b

NameError: name ‘b‘ is not defined

In [111]: def x():
    b = 12
    def y():
        global a,b
        a = 1
        print b
    y()
    print "b =",b
   .....:     

In [112]: x()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-112-7354d77c61ac> in <module>()
----> 1 x()

<ipython-input-111-c05fc67a1e82> in x()
      5         a = 1
      6         print b
----> 7     y()
      8     print "b =",b
      9 

<ipython-input-111-c05fc67a1e82> in y()
      4         global a,b
      5         a = 1
----> 6         print b
      7     y()
      8     print "b =",b

NameError: global name ‘b‘ is not defined

   这就确定了 内层y() 的 global 不会 导入 x() 的东西。

   那么,内层函数怎么使用正确的外层函数的变量呢?

解决内层函数参数传递问题

  

  一、

  首先,若只是取值,则不需要做任何处理。

In [119]: def x():
   .....:     a = 12
   .....:     def y():
   .....:         print a
   .....:     y()
   .....:     

In [120]: x()
12

In [121]: 

  在 y() 中,一旦为 a 赋值,a 立马变内部变量。

In [121]: def x():
   .....:     a = 12
   .....:     def y():
   .....:         print "before a =",a
   .....:         a = 1
   .....:         print "then a =",a
   .....:     y()
   .....:     

In [122]: x()
before a =---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
<ipython-input-122-7354d77c61ac> in <module>()
----> 1 x()

<ipython-input-121-d8fbc0dba399> in x()
      5         a = 1
      6         print "then a =",a
----> 7     y()
      8 

<ipython-input-121-d8fbc0dba399> in y()
      2     a = 12
      3     def y():
----> 4         print "before a =",a
      5         a = 1
      6         print "then a =",a

UnboundLocalError: local variable ‘a‘ referenced before assignment

  一旦在函数 y() 的某处给 a 赋值,则在赋值前,python 会认为 a 不存在。

  同时发现 python2 的 print 会一个一个的 输出。鉴于此,我又在 python3 中试了,发现他是 一起输出。但这不是本文重点,折叠之。

In [7]: def x():
    a = 1
    def y():
        print("before a=",a)
        a = 10
        print("then a=",a)
    y()
   ...:     

In [8]: x()
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
<ipython-input-8-7354d77c61ac> in <module>()
----> 1 x()

<ipython-input-7-6e01e7317b24> in x()
      5         a = 10
      6         print("then a=",a)
----> 7     y()
      8 

<ipython-input-7-6e01e7317b24> in y()
      2     a = 1
      3     def y():
----> 4         print("before a=",a)
      5         a = 10
      6         print("then a=",a)

UnboundLocalError: local variable ‘a‘ referenced before assignment

  

  同时发现 python代码运行前 会先扫一遍代码的,而不是单纯的一行一行的执行。

  同时发现返回 UnboundLocalError,而不是 NameError。注意到 ’unbound‘,这是官方概念。用 ’unbound‘ 来描述就是:global 会将顶层变量名称 绑定 到本地变量名称,同时变化,是为 ’引用‘;python 检测到 a = 1时,意识到 a 是本地的,所以 在 a ’指向一个对象‘(因为python变量均为引用),之前 ,调用 a 是非法 行为,但这种行为区别于于 NameError,就定义为 unbound local。

  二、

  使用 可变变量,如 list,dict

  

In [127]: def x():
   .....:     l = ["in msg"]
   .....:     def y():
   .....:         msg = l[0]
   .....:         print "msg =",msg
   .....:         l[:] = ["out msg"]
   .....:     y()
   .....:     print l[0]
   .....:     

In [128]: x()
msg = in msg
out msg

  

  没有报错,完美!

  要注意 语句  l[:] = ["out msg"] ,使用切片赋值,否则,

In [129]: def x():
    l = ["in msg"]
    def y():
        msg = l[0]
        print "msg =",msg
        l = ["out msg"]
    y()
    print l[0]
   .....:     

In [130]: x()
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
<ipython-input-130-7354d77c61ac> in <module>()
----> 1 x()

<ipython-input-129-d44e750e285f> in x()
      5         print "msg =",msg
      6         l = ["out msg"]
----> 7     y()
      8     print l[0]
      9 

<ipython-input-129-d44e750e285f> in y()
      2     l = ["in msg"]
      3     def y():
----> 4         msg = l[0]
      5         print "msg =",msg
      6         l = ["out msg"]

UnboundLocalError: local variable ‘l‘ referenced before assignment

  又出 UnboundLocalError 了,因为 第六行代码 为 l 分配了 一个新的 list。

  

  三、

  利用参数传递。

  

In [136]: def x():
   .....:     a, b = 1, 2
   .....:     def y(a = a, b = b):
   .....:         a, b = 3, 4
   .....:         return a, b
   .....:     a, b = y()
   .....:     print a, b
   .....:     

In [137]: x()
3 4

  注意,不要在默认参数上放 list等可变对象。

  原创,欢迎指正。

  本文完。

时间: 2024-08-29 06:23:42

python 中使用 global,莫名其妙的问题的相关文章

python中的关键字global和nonlocal

知识点: global将一个变量变为全局变量 nonlocal改变最近的变量,又不是全局作用. 1.global 在python中,当引用一个变量的时候,对这个变量的搜索按找本地作用域(Local).嵌套作用域(Encolosing function locals).全局作用域(Global).内置作用域(builtins模块)的顺序来进行的,即所谓的LEGB规则. m = 1 #全局 def fun1(): m = 2 #嵌套 def fun2(): m = 3 #本地 fun2() fun1

python中的nonloca和global

在python中,每一个变量都含有自己的定义域,甚至相同名字的变量在不同的函数内都有着不同的定义域,实际上,相同的变量名在不同的函数中就已经不是同一个函数了,因为该变量的定义域被改变了,一个定义域在模块级别的变量如果不加修饰的被封锁在函数内部,即便名字相同,但实际上也是俩个不同的变量.其在函数内部被引用时,实际上是在函数内部又创造了一个与该变量相同名字(但在内存中位置不同)的变量,请看下面的例子: count一开始作为定义域在模块级别的变量被定义,而在函数内部仅仅作为他的一个副本被使用.也可以看

简单介绍下python中函数的基础语法

python 函数 定义 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可. 特性 减少代码重复 使程序变得可扩展 使程序变得易于维护 函数的创建 python中创建函数,需要使用__def__关键字,后面写函数的名字,然后是形参列表,大体如下: def 函数名(形参列表): 函数体...... return 返回值 其中形参列表和 return返回值并不是必须的. 函数的使用 想要调用函数程序,需要以函数名加括号的形式进行调用,而括号内可以传入参数

python中的进程、线程(threading、multiprocessing、Queue、subprocess)

Python中的进程与线程 学习知识,我们不但要知其然,还是知其所以然.你做到了你就比别人NB. 我们先了解一下什么是进程和线程. 进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CPU是计算机的核心,它承担计算机的所有任务. 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资源的管理和分配.任务的调度. 程序是运行在系统上的具有某种功能的软件,比如说浏览器,音乐播放器等. 每次执行程序的时候,都会完成一定的功能,比如说浏览器帮我们打开网页,为了保证其独立性,就需要一个专

Python中urlopen()介绍

#以下介绍是基于Python3.4.3 一.  简介   urllib.request.urlopen()函数用于实现对目标url的访问. 函数原型如下:urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None) 函数定义如下: def urlopen(url, data=None, timeout=socket._GLOBAL_DEFA

理解 Python 中的线程

原地址:http://blog.jobbole.com/52060/ 本文由 伯乐在线 - acmerfight 翻译自 Akshar Raaj.欢迎加入技术翻译小组.转载请参见文章末尾处的要求. 我们将会看到一些在Python中使用线程的实例和如何避免线程之间的竞争.你应当将下边的例子运行多次,以便可以注意到线程是不可预测的和线程每次运行出的不同结果.声明:从这里开始忘掉你听到过的关于GIL的东西,因为GIL不会影响到我想要展示的东西. 示例1 我们将要请求五个不同的url: 单线程 1 2

Python中的eval()、exec()及其相关函数

Python中的eval().exec()两个函数以及与它们相关的几个函数,如globals().locals()和compile(): 1. eval函数 函数的作用: 计算指定表达式的值.也就是说它要执行的Python代码只能是单个运算表达式(注意eval不支持任意形式的赋值操作),而不能是复杂的代码逻辑,这一点和lambda表达式比较相似. 函数定义: eval(expression, globals=None, locals=None) 参数说明: expression:必选参数,可以是

Python中变量的作用域(variable scope)

http://www.crifan.com/summary_python_variable_effective_scope/ 解释python中变量的作用域 示例: 1.代码版 1 #!/usr/bin/python 2 # -*- coding: utf-8 -*- 3 """ 4 ------------------------------------------------------------------------------- 5 Function: 6 [整理

(转载)Python中:self和__init__的含义 +

(注:原文地址 Python中:self和__init__的含义 + 为何要有self和__init__) 背景 回复: 我写的一些Python教程,需要的可以看看 中SongShouJiong的提问: Python中的self,__init__的含义是啥? 为何要有self,__init这些东西? 解释之前,先说几句 1.到目前为止,我虽然也已写了不算很少的python的代码,但是,还真的没有太多接触self和__init__这两个东西. 只能算是大概了解. 2.为了搞懂其含义,现学现卖,去看