浅谈Python3中访问变量的顺序问题及global和nonlocal关键字的用法

浅谈Python3中访问变量的顺序问题及global和nonlocal关键字的用法

  • 一、前言
  • 二、全局变量和局部变量
  • 三、变量调用的顺序
  • 四、global和nonlocal用法
  • 五、实例演示

一、前言

今天在看看学习视频时,忽然记不起nonlocal的用法,然后就翻书和搜索,顺带去翻看了help文档,发现里面讲的很清楚。所以分享如下,可能有些地方理解有点偏颇,所以有些会放官方文档的部分出来,说的不对的地方, 还请大家多多指导。

二、全局变量和局部变量

全局变量:作用在全局的变量,即定义在模块内,且在函数外的变量。它可以被模块内的所有函数使用。不过这里需要注意访问先后问题,待会讲。全局变量直到程序结束(模块退出时)才被销毁。
局部变量:作用在局部的变量,即定义在函数内的变量。它作用在两个地方,第一个是定义它的函数;第二个是定义这个局部变量的子孙函数(即该函数里面的嵌套函数),不能够在这个函数的外部被调用。它会在这个函数返回或引发函数内未处理的异常时被销毁。
这里需要提一句当然,递归调用每个都有自己的局部变量,需要最后一层一层的返回

三、变量调用的顺序

这里放上原文,附带个人理解,欢迎大家留言指正
Although scopes are determined statically, they are used dynamically. At any time during execution, there are at least three nested scopes whose namespaces are directly accessible:

  1. the innermost scope, which is searched first, contains the local names # 第一、先从本函数查找
  2. the scopes of any enclosing functions, which are searched starting with the nearest enclosing scope, contains non-local, but also non-global names # 第二,闭包函数时,往下查找,从最近的闭包函数开始查找,这个暂时理解不深。
  3. the next-to-last scope contains the current module global names # 第三、一层一层网上查找,查找到模块定义的全局变量
  4. the outermost scope (searched last) is the namespace containing built-in names # 第四、最后是查找最外层,即查找内置的变量,最后还没有找到就返回异常

四、global和nonlocal用法

官方解释:

If a name is declared global, then all references and assignments go directly to the middle scope containing the module抯 global names. To rebind variables found outside of the innermost scope, the nonlocal statement can be used; if not declared nonlocal, those variables are read-only (an attempt to write to such a variable will simply create a new local variable in the innermost scope, leaving the identically named outer variable unchanged).

global:是用来在函数内声明全局变量,从而可以实现在函数内改变全局变量。如果没有用global声明,而是用赋值操作等号,那么会在该函数内新建一个局部变量,同名的全局变量不受影响。如有全局变量n = 4,在一个函数中定义n=,8,那么该函数会新建一个局部变量n并赋值为8,而同名的全局变量n仍然为4。
nonloca:用在函数里面有嵌套函数的时候,实现内嵌的子孙函数可以对父辈及爷爷辈以上的函数变量进行改变。如果未用nonlocal声明,也是相当于创建一个局部变量,不会影响外部同名变量的值。

五、实例演示

这里给出的是官方文档给的示例:

def scope_test():
    def do_local():
        spam = "local spam" # 创建一个新的同名局部变量,不影响外部的spam变量的值

    def do_nonlocal(): # scope_test()函数的子函数
        nonlocal spam # 实现对于上一级scope_test()函数中spam变量的改变
        spam = "nonlocal spam" # 调用do_nonlocal()后,scope_test()的spam变量值会改变

    def do_global():# scope_test()函数的子函数
        global spam # 将spam声明为全局变量
        spam = "global spam" # # 重新给全局变量spam赋值

    spam = "test spam" # 创建scope_test()函数的局部变量
    
    do_local()
    print("After local assignment:", spam) # do_local()未改变scope_test()的spam
    
    do_nonlocal()
    print("After nonlocal assignment:", spam)# do_nonlocal()改变了scope_test()的spam
    
    do_global()
    print("After global assignment:", spam) # 虽然do_global()声明全局变量spam,并且改变了值
    # 但是按照访问顺序,先查找scope_test()内的spam,找到就结束了,这里注意前面调用了do_nonlocal()
    # 所以scope_test()函数的spam值已经变为nonlocal spam
    
scope_test()
print("In global scope:", spam) # 因为scope_test()调用结束,里面的局部变量全部被销毁,这里访问的是全局变量spam=global spam


# 下面是输出的结果
After local assignment: test spam
After nonlocal assignment: nonlocal spam
After global assignment: nonlocal spam
In global scope: global spam

后记:
我从本硕药学零基础转行计算机,自学路上,走过很多弯路,也庆幸自己喜欢记笔记,把知识点进行总结,帮助自己成功实现转行。
2020下半年进入职场,深感自己的不足,所以2021年给自己定了个计划,每日学一技,日积月累,厚积薄发。
如果你想和我一起交流学习,欢迎大家关注我的微信公众号每日学一技,扫描下方二维码或者搜索每日学一技关注。
这个公众号主要是分享和记录自己每日的技术学习,不定期整理子类分享,主要涉及 C – > Python – > Java,计算机基础知识,机器学习,职场技能等,简单说就是一句话,成长的见证!
每日学一技

你可能感兴趣的:(Python,局部变量,全局变量,nonlocal,global,Python)