最近看 scala ,看到了它的作用域,特此回顾一下python的变量作用域问题。

A = 10
B = 100
print A #10
print globals() #{'A': 10, 'B': 100, '__builtins__': <module '__builtin__' (built-in)>, '__file__': 'E:/PycharmProjects/untitled/test1.py', '__package__': None, '__name__': '__main__', '__doc__': None} def mu(x,y):
B = 9
print locals() #{'y': 9, 'x': 10,'B':9}
if A == 10:
B = 19
print locals() #{'y':9,'x':10,'B':19}
return x+y
else:
return x-y m = mu(10,9)
print(m) # 19
print locals() #{'A': 10, 'B': 100, '__builtins__': <module '__builtin__' (built-in)>, '__file__': 'E:/PycharmProjects/untitled/test1.py', 'm': 19, '__package__': None, 'mu': <function mu at 0x02ADA430>, '__name__': '__main__', '__doc__': None}
print globals()#{'A': 10, 'B': 100, '__builtins__': <module '__builtin__' (built-in)>, '__file__': 'E:/PycharmProjects/untitled/test1.py', 'm': 19, '__package__': None, 'mu': <function mu at 0x02ADA430>, '__name__': '__main__', '__doc__': None} # 全局作用域的 locals 和globals 内的变量内容是一样的。
print __name__ # __main__
print __file__ #E:/PycharmProjects/untitled/test1.py
print __doc__ # None
print __package__ # None print B # 100

global


A = 10
B = 100
print A # 10
print globals()#{'A': 10, 'B': 100, '__builtins__': <module '__builtin__' (built-in)>, '__file__': 'E:/PycharmProjects/untitled/test1.py', '__package__': None, '__name__': '__main__', '__doc__': None} def mu(x,y):
global B
B +=1
print(B) #101
print locals() #{'y': 9, 'x': 10} 进过global 作用, 本地变量中不会创建新的本地变量 B 了。而是直接用的全局的 B。
if A == 10:
B = 20
print locals() #{'y': 9, 'x': 10}
return x+y
else:
return x-y m = mu(10,9)
print(m)
print locals() #{'A': 10, 'B': 20, '__builtins__': <module '__builtin__' (built-in)>, '__file__': 'E:/PycharmProjects/untitled/test1.py', 'm': 19, '__package__': None, 'mu': <function mu at 0x02A8A430>, '__name__': '__main__', '__doc__': None} print globals()#{'A': 10, 'B': 20, '__builtins__': <module '__builtin__' (built-in)>, '__file__': 'E:/PycharmProjects/untitled/test1.py', 'm': 19, '__package__': None, 'mu': <function mu at 0x02A8A430>, '__name__': '__main__', '__doc__': None} print B#20 因为函数中使用了 global 关键字, 函数中使用的是全局变量B ,并且对其做出了修改,所以这个B也就变成了 20

赋值 操作

A = 10
B = 100
print A
print globals() def mu(x,y):
# B = B +1 # 这么做会报错 因为赋值操作会查找 本地变量 然而本地变量中并没有B 变量 并不是想象中的 B = 100 +1 ,只要出现赋值语句,就会遮蔽外层变量,而在此之前,本地变量中并未定义B。
# print(B) #100
print locals()
if A == 10:
if B == 100: #这么做不会报错,它会查找到全局变量
print "haha"
print locals() #{'y': 9, 'x': 10}
return x+y
else:
return x-y m = mu(10,9)
print(m)
print locals()
print globals()
print B #100

以下为python3 操作

>>> def a(x):
... print(x)
... def b():
... print(x) # 参数作用域,父函数的参数可以 被子函数所使用,这也就是闭包。scala 作用域与此效果类似,内部函数,可以直接使用外部函数的变量。
... b()
...
>>>
>>> a(10)
10
10
>>> def a(x):
... print(x)
... def b():
... print(x) #这里会报错,因为在一旦在函数内部出现赋值操作,那么就会对外层的变量产生遮蔽效果,无论这赋值参数在本函数内部的位置是否在前,或者是在后,只要出现,就会出现遮蔽效果,此时如果在赋值操作之前使用该变量,就会出现未定义该变量的错误。 scala 的变量作用域效果与此类似。
... x = 20
... print(x)
... b()
...
>>> a(10)
10
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 7, in a
File "<stdin>", line 4, in b
UnboundLocalError: local variable 'x' referenced before assignment
>>> def a(x):
... print(x)
... def b():
... nonlocal x #python3 的 nonlocal 语句可以内部函数直接使用外部函数
... x = 20
... print(x)
... b()
... print(x)
...
>>> a(10)
10
20
20 >>> def a(x):
... print(locals())
... def b():
... print(x)
... print(locals())
... b()
...
>>> a(1)
{'x': 1}
1
{'x': 1}
>>> def a(x):
... print(locals())
... def b():
... print(locals()) #虽然赋值操作在本打印语句之后,但是仍然 可以看出,x 已经被遮蔽了
... x = 20 #由于未使用nonlocal,此时的x 是一个和外部x 同名的全新的本地变量,所以,对他的任何修改,仅限于本函数内部,不会影响到外部。
... print(locals())
... print(x)
... b()
... print(x) # 这是 遮蔽效果的证明
...
>>> a(10)
{'x': 10}
{}
{'x': 20}
20
10
>>>

闭包

def a():
x = 20
def b(y):
return y+x # 注意闭包内部是直接使用 外层函数的变量,而没有对外层函数变量进行赋值操作。
return b(10) def c():
x = 20
def b(y):
x += 12 # 这里对x 进行了赋值操作。 x = x+12 ,这会报错,这其实已经不是闭包了,由于出现了赋值操作,所以,这里的 x 是一个和外层同名的变量,但是在本函数内部,本等式之前,并未进行 x 的宣告。所以会报错
return x +y
return b(10) print(c())

贴一段scala 的闭包代码:

object PackageStudy {
def main(args: Array[String]): Unit = {
def a(): Int = {
var x = 10
def b(y: Int): Int = {
x += 13 // scala 可以做此操作,对捕获的自由变量进行了修改,但是 python 不行,因为这个操作在python 内部是一个重新宣告x,重新赋值的操作,这会产生屏蔽效果,python 宣告变量 是“贴签”操作。所以,python貌似是不支持对捕获变量的修改。也就没有 所谓在函数内部进行修改,会影响 外部的自由变量的值 这种情况的出现。
x + y
}
def c(z: Int): Int = {
x + z
}
println(x) //10
println(b(10)) //33 第一次捕获的自由变量的值是 x =10,所以此时的函数字面量中 x 绑定的是10
println(x) //23 //在闭包内部对捕获的自由变量的修改,也会影响到外面的自由变量。
println(c(3)) //26 自由变量经过 b() 的修改,c(3)再次捕获x时,x 已经是 23 了,此时的 函数字面量中绑定的x 是23
0
}
println(a())
}
}

python引用变量的顺序: 当前作用域局部变量->外层作用域变量->当前模块中的全局变量->python内置变量 。

python 本地变量和全局变量 locals() globals() global nonlocal 闭包 以及和 scala 闭包的区别的更多相关文章

  1. Python 私有变量中两个下划线 _ _item 与 一个下划线的区别 _item

    python中没有常量的说法, 但是可以通过元组实现一个常量 在python的私有变量中, 存在两个下划线 _ _item 与一个下划线 _item 的区别 前面带两个下划线的私有变量: 只能在本类中 ...

  2. Python 基础之返回值与函数使用与局部变量和全局变量locals() 和 globals()

    一.函数的返回值 return return: 自定义返回值,返回到哪里? 返回到函数的[调用处]1.return 后面可以跟上六个标准数据类型,除此之外,可以跟上 类对象,函数,如果不写return ...

  3. 说几个python与c区别的地方以及静态变量,全局变量的区别

    一: python代码: a = 2 def b(): print a a = 4 print a b() 在b函数中,有a=4这样的代码,说明a是函数b内部的局部变量,而不是外部的那个值为2的全局变 ...

  4. python中list作为全局变量无需global声明的原因

    发现一个问题. python中list变量作为全局变量时,在函数中可以直接修改. 而普通变量则需要先在函数中global声明,否则会报错. 例如: a = 1 def fun(): global a ...

  5. PHP中全局变量的使用global和$GLOBALS[]

    From: http://blog.csdn.net/happyqyt/article/details/7219889 用PHP开发项目,不可避免的会使用到全局变量,比如一些网站的配置信息,全站通用, ...

  6. python开发_python中的变量:全局变量和局部变量

    如果你在为python中的变量:全局变量和局部变量头疼,我想这篇blog会给你帮助 运行效果: 代码部分: #Python中的变量:全局变量和局部变量 #在很多语言中,在声明全局变量的时候,都喜欢把全 ...

  7. python课堂整理10---局部变量与全局变量

    一.局部变量与全局变量 1. 没有缩进,顶头写的变量为全局变量 2. 在子程序里定义的变量为局部变量 3. 只有函数能把变量私有化 name = 'lhf' #全局变量 def change_name ...

  8. C语言学习--全局变量、静态本地变量

    全局变量 全局变量 定义在函数外面的变量是全局变量 全局变量具有全局的生存期和作用域 它们与任何函数无关 在任何函数内部都可以使用它们 #include <stdio.h> int f(v ...

  9. python 得到变量名的结果为名的变量的值locals()

    >>> a="1">>> b="a">>> print(a,b)1 a>>> print ...

随机推荐

  1. sql 判断 数据库 表 字段 是否存在

    select * From master.dbo.sysdatabases where name='数据库名'select * from sysobjects where id = object_id ...

  2. js 正则用空格分割字符串

    var filename = "ASDFK*SADF+ALDLAS-LDKFADFa*seAc tion.java";var arr = filename.split(/\*|\- ...

  3. 垃圾收集器之:CMS收集器

    HotSpot JVM的并发标记清理收集器(CMS收集器)的主要目标就是:低应用停顿时间.该目标对于大多数交互式应用很重要,比如web应用.在我们看一下有关JVM的参数之前,让我们简要回顾CMS收集器 ...

  4. 小甲鱼-003 python插曲值变量和字符串

    变量名就像现实生活人们的名字,把一个值赋值给一个名字时,他会存储在内存中,称之为变量variable,在大多数语言中,都把这种行为成为"给变量赋值"或"把值存储在变量中& ...

  5. ssh-keygen的使用方法(无密码访问)

    一.概述 1.就是为了让两个linux机器之间使用ssh不需要用户名和密码.采用了数字签名RSA或者DSA来完成这个操作 2.模型分析 假设 A (192.168.20.59)为客户机器,B(192. ...

  6. linux设置iptables防火墙的详细步骤(centos防火墙设置方法)

    CentOS系统也是基于linux中的它的防火墙其实就是iptables了,下面我来介绍在CentOS防火墙iptables的配置教程,希望此教程对各位朋友会有所帮助.   iptables是与Lin ...

  7. HttpURLConnection连接超时问题

    1.问题描述 这几天测试重构后的下载框架,发现在下载过程中如果网络中断或网络较差,个别应用的下载就会阻塞卡住,一直卡在 “正在下载 xx%”.   2.问题排查和定位 思考:网络差不应该报网络异常的错 ...

  8. seaborn可视化特征的相关性

    import seaborn as sn sn.heatmap(trainX.corr(),vmax=1,square=True)

  9. VS Code 基本介绍 和 快捷键

    简介 VSCode是微软推出的一款轻量编辑器,采取了和VS相同的UI界面,搭配合适的插件可以大幅提升前端开发的效率. 布局:左侧是用于展示所要编辑的所有文件和文件夹的文件管理器,依次是:资源管理器,搜 ...

  10. Web 数据源

    问题描述: ClassCastException:类型转换异常 问题代码: private static LinkedList<Connection> pool = (LinkedList ...