欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程语言 > python >内容正文

python

python local variable_python学习笔记 - local, global and free variable

发布时间:2024/9/19 python 45 豆豆
生活随笔 收集整理的这篇文章主要介绍了 python local variable_python学习笔记 - local, global and free variable 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

理解 global and local variable

现在我想在子代码块中对global variable重新赋值,实现代码如下:

code snippet 1

>>>

>>> var = 'outer val'

>>> def func1():

... var = 'inner val'

... print "Inside func1(), val: ", var

... print "locals(): ", locals()

... print "globals(): ", globals()

...

>>> func1()

Inside func1(), val: inner val

locals(): {'var': 'inner val'}

globals(): {'func1': , '__builtins__': , '__package__': None, 'var': 'outer val', '__name__': '__main__', '__doc__': None}

>>>

>>> print "var: ", var

var: outer val

>>>

但结果并非如我所愿。在func1内部,var的值为"inner val",离开了函数,其值又变成了"outer val",为什么?看看输出的本地和全局变量列表答案就明显了,var既出现在本地变量列表,又出现在全局变量列表,但绑定的值不一样,因为他们本就是两个不同的变量。也就是说,当你想在子代码块中对某个全局变量重新赋值时,实际上你只是定义了一个同名的本地变量,这并不会改变全局变量的值。

如何修改全局变量的值?需要在函数中使用global statement。先看一例:

code snippet 2

>>> def func2():

... global var2

... var2 = 'who am i'

... print "locals(): ", locals()

... print "globals(): ", globals()

...

>>> func2()

locals(): {}

globals(): {'func2': , 'func1': , 'var2': 'who am i', '__builtins__': , '__package__': None, '__name__': '__main__', '__doc__': None}

>>>

>>> print var2

who am i

>>>

看看输出结果,发现竟然可以在函数代码块中定义一个全局变量,太神奇了!因为全局变量的作用域是整个模块,所以离开了定义函数,依然可以读取它。

有了这个做铺垫,再来尝试修改全局变量的值:

code snippet 3

>>> global_var = 'outer'

>>> def func3():

... global global_var

... global_var = 'inner'

... print "locals(): ", locals()

... print "globals(): ", globals()

...

>>> func3()

locals(): {}

globals(): {'func3': , '__builtins__': , 'global_var': 'inner', '__package__': None, '__name__': '__main__', '__doc__': None}

>>>

>>> print global_var

inner

>>>

妥妥的了。做个总结吧,要在函数代码块中修改全局变量的值,就使用global statement声明一个同名的全局变量,然后就可以修改其值了;如果事先不存在同名全局变量,此语句就会定义一个,即使离开了当前函数也可以使用它。

理解 global and free variable

来自于python官方文档 Execution Model 的解释:

When a name is used in a code block, it is resolved using the nearest enclosing scope. The set of all such scopes visible to a code block is called the block’s environment.

If a name is bound in a block, it is a local variable of that block. If a name is bound at the module level, it is a global variable. (The variables of the module code block are local and global.) If a variable is used in a code block but not defined there, it is a free variable.

这段文档确实应该多读多想。全局变量不用多说,一看就懂。不过这句话有点让人费解,“The variables of the module code block are local and global”,我是这样理解的,对于模块代码块来说,模块级的变量就是它的本地变量,但对于模块中其他更小的代码块来说,这些变量就是全局的。那再进一步,什么是模块级的变量,是指那些在模块内部,但在其所有子代码块之外定义的变量吗?用代码验证哈:

code snippet 4

>>>

>>> global_var = 'global_val'

>>> def showval():

... local_var = 'local_val'

... print "before defining inner func, showval.locals(): ", locals()

... def innerFunc():

... print "Inside innerFunc, local_var: ", local_var

... print "innerFunc.locals:", locals()

... print "after defining inner func, showval.locals(): ", locals()

... print "showval.globals():", globals()

... return innerFunc

...

>>> a_func = showval()

before defining inner func, showval.locals(): {'local_var': 'local_val'}

after defining inner func, showval.locals(): {'innerFunc': , 'local_var': 'local_val'}

showval.globals(): {'__builtins__': , 'global_var': 'global_val', '__package__': None, '__name__': '__main__', '__doc__': None, 'showval': }

>>>

>>> a_func

>>> a_func()

Inside innerFunc, local_var: local_val

innerFunc.locals: {'local_var': 'local_val'}

>>>

基于自己的理解来分析哈输出结果:变量local_var、函数innerFunc是在函数代码块showval中定义的,所以它们是该代码块的局部变量。首次输出globals时,变量global_var、函数showval在所有子代码块之外定义,所以它们是当前模块的全局变量。再次输出globals时,多了一个全局变量globals。

注意看,全局变量中还有:__builtins__、__package__、__name__、__doc__。这些变量的含义可参考 python模块的内置方法。

现在来看自由变量,local_var被innerFunc函数使用,但是并未在其中定义,所以对于innerFunc代码块来说,它就是自由变量。问题来了,自由变量为什么出现在

innerFunc.locals()的输出结果中?这就需要看看locals()API文档了:

Update and return a dictionary representing the current local symbol table. Free variables are returned by locals() when it is called in function blocks, but not in class blocks.

好像我已经把自由变量搞得很清楚了,但是真的吗?看看下面的代码:

code snippet 5

>>>

>>> global_var = 'foo'

>>> def ex1():

... local_var = 'bar'

... print "locals(): ", locals()

... print global_var

... print local_var

... global_var = 'foo2'

...

>>> ex1()

locals(): {'local_var': 'bar'}

Traceback (most recent call last):

File "", line 1, in

File "", line 4, in ex1

UnboundLocalError: local variable 'global_var' referenced before assignment

>>>

>>> def ex2():

... local_var = 'bar'

... print "locals(): ", locals()

... print "globals(): ", globals()

... print global_var

... print local_var

...

>>> ex2()

locals(): {'local_var': 'bar'}

globals(): {'__builtins__': , 'global_var': 'foo', '__package__': None, 'ex2': , 'ex1': , '__name__': '__main__', '__doc__': None}

foo

bar

>>>

首先分析哈输出结果。执行ex1()函数失败,原因:UnboundLocalError: local variable 'global_var' referenced before assignment,意思是global_var这个本地变量还未赋值就被引用了。等等,global_var怎么是本地变量了?与ex2()函数做个对比,发现因为有这行代码global_var = 'foo2',解释器就认为global_var是一个本地变量,而不是全局变量。

那最外面定义的global_var到底是本地还是全局变量?看看第二部分的输出,可以很确定地知道最外面定义的global_var是一个全局变量。

简单点说,就是这里存在两个同名的变量,一个是最外面定义的全局变量global_var,另一个是函数ex1()中定义的本地变量global_var。

再等等,矛盾出现了。按照之前对自由变量的理解,在一个代码块中被使用,但是并未在那儿定义,外部定义的global_var在函数块ex1()中被使用,完全符合,它为什么不是一个自由变量?还是我们对自由变量的理解有问题?

与code snippet 4中确定是自由变量的local_var比较,发现local_var是一个函数代码块的本地变量,而code snippet 5中的global_var是一个模块代码块的本地变量。当local_var被定义它的函数内的嵌套函数使用时,它就变成了一个自由变量,此时函数的嵌套就形成了闭包(closure),可见自由变量的应用场景就是闭包。

而global_var对模块本身来说它是一个本地变量,但在模块中的其他代码块中也可以使用它,所以它同时又是一个全局变量。

到这儿就可以对自由变量的理解做个总结了:如果一个变量在函数代码块中定义,但在其他代码块中被使用,例如嵌套在外部函数中的闭包函数,那么它就是自由变量。注意,给变量赋值不算是使用该变量,使用指的是读取变量值,具体区别后面再详述。

理解 free and local variable

修改全局变量的值需要使用global,那修改自由变量的值又会如何?先用自然思维方式试试:

code snippet 6

>>>

>>> def outerfunc():

... var = 'free'

... def innerfunc():

... var = 'inner'

... print "Inside innerfunc, var: ", var

... print "Inside innerfunc, locals(): ", locals()

... innerfunc()

... print "var: ", var

... print "locals(): ", locals()

...

>>> outerfunc()

Inside innerfunc, var: inner

Inside innerfunc, locals(): {'var': 'inner'}

var: free

locals(): {'var': 'free', 'innerfunc': }

>>>

在innerfunc函数中我试图修改自由变量var的值,结果却发现修改只在innerfunc函数内有效,离开此函数后其值仍然是"free"。看看输出的outerfunc和innerfunc函数的本地变量列表就知道咋回事儿了。当你想在闭包函数中对自由变量重新赋值时,实际上你只是在这里定义了一个本地变量,这并不会改变自由变量的值。

code snippet 7

class Namespace: pass

def ex7():

ns = Namespace()

ns.var = 'foo'

def inner():

ns.var = 'bar'

print 'inside inner, ns.var is ', ns.var

inner()

print 'inside outer function, ns.var is ', ns.var

ex7()

# console output

inside inner, ns.var is bar

inside outer function, ns.var is bar

code snippet 8

def ex8():

ex8.var = 'foo'

def inner():

ex8.var = 'bar'

print 'inside inner, ex8.var is ', ex8.var

inner()

print 'inside outer function, ex8.var is ', ex8.var

ex8()

# console output

inside inner, ex8.var is bar

inside outer function, ex8.var is bar

参考资源:

与50位技术专家面对面20年技术见证,附赠技术全景图

总结

以上是生活随笔为你收集整理的python local variable_python学习笔记 - local, global and free variable的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。