转载自CSDN 雁丘1990, 原文地址: https://blog.csdn.net/xcyansun/article/details/79672634

这篇文章写的很赞, 条理清晰, 分析循序渐进, 感谢原作者!

结论:

第一,两者的功能不同。global关键字修饰变量后标识该变量是全局变量,对该变量进行修改就是修改全局变量,而nonlocal关键字修饰变量后标识该变量是上一级函数中的局部变量,如果上一级函数中不存在该局部变量,nonlocal位置会发生错误(最上层的函数使用nonlocal修饰变量必定会报错)。

第二,两者使用的范围不同。global关键字可以用在任何地方,包括最上层函数中和嵌套函数中,即使之前未定义该变量,global修饰后也可以直接使用,而nonlocal关键字只能用于嵌套函数中,并且外层函数中定义了相应的局部变量,否则会发生错误(见第一)

我们先来看一个代码片段,看看默认情况下输出结果是什么。

输出结果:

上面的代码片段中没有使用global或nonlocal关键字,是为了看一下默认情况下的输出结果。

可以看到变量x在三次输出中是同一个变量(值相同,地址也相同),都是全局变量,在print函数中使用三个参数是为了方便识别变量,第一个参数是print运行的位置,第二个参数是变量x保存的值,第三个参数是变量x保存的值的地址(这个有待考证)。

如果我们在func函数中修改x的值呢?

输出结果:

可以看到func函数中x的值和地址都变了,但没有影响函数外边的x的值和地址(main1和main2的数据相同)。所以func函数内的x变量和函数外的x变量是两个变量,而func内的x变量是局部变量,修改它的值不影响全局变量。

第一回合:在函数内部使用了与全局变量同名的变量,如果不对该变量赋值(修改变量),那么该变量就是全局变量,如果对该变量进行赋值,那么该变量就是局部变量。

如果我们想在func函数内修改全局变量x呢?我们先试试用global(全局)。

运行后报错,提示语法错误。原来global修饰变量时不能直接赋值,修改为如下:

运行结果:

可以看到main1位置的x和func内部func1位置的x是同一个值,但和func内部的func2以及main2位置的x不一样了,反而是main2处的x和func内部的x变量是同一个。

第二回合:global关键字修饰函数内部变量后标志其是全局变量(这里不能说global将x从局部变量改为了全局变量),如果用global修饰函数内的变量,必须在使用该变量前进行修饰(否则会发生变量未定义的错误,请你自己尝试一下)

我们试试nonlocal关键字呢?

报错了,无法使用nonlocal关键字。

接下来我们看看怎样使用nonlocal关键字。

我们先添加一个嵌套函数:

输出结果:

可以看到嵌套函数内默认使用的也是全局变量。我们在func函数中修改一下x的值试试。

输出结果:

可以看到在func函数中修改x后,x被标识成局部变量,它的改变并没有影响全局变量x,但嵌套函数ifunc中的x受到了影响,显示ifunc中的x是func函数中的局部变量。

我们再继续修改一下ifunc中x的值。

输出结果:

可以看到在ifunc修改x的之后即没有影响func中的局部变量x,也没有影响全局变量x,ifunc中的x是函数ifunc自己的局部变量。

第三回合:如果在嵌套函数和函数(这里指包含嵌套函数的那个函数)中存在和全局变量同名的变量,如果直接使用,而不修改变量的值,那么这三个位置的变量使用的是同一个全局变量,如果在函数中修改了变量值,那么该变量会被标识为该函数的局部变量,嵌套函数直接使用时使用的是该函数的局部变量。如果在嵌套函数中修改同名变量的值,那么嵌套函数中的该变量会被标识为该嵌套函数的局部变量,它的修改不影响函数中同名变量和全局变量

我们在嵌套函数中添加global关键字试试。

先不修改ifunc中x的值:

输出结果:

可以看出嵌套函数ifunc中的x是全局变量。

再修改一下ifunc中x的值试试:

输出结果:

可以看出嵌套函数中x是全局变量,但它的修改没有影响到func函数中的同名局部变量。

我们在前边已经发现在func函数中直接使用nonlocal关键字发生了报错,我们再试试在ifunc中使用nonlocal关键字:

输出结果:

可以看到nonlocal修饰后,ifunc中的x和func中的x是同一个变量,ifunc中修改x的值影响了func中的x(因为是一个变量),但并没有影响全局变量x。

再扩展一下:

在func函数中用global修饰x并修改ifunc中x的值,看看有什么变化:

输出结果:

我们再用nonlocal修饰一下ifunc函数中的x:

运行时发生报错,提示没有为ifunc中的x找到绑定。

第四回合:global可以在任何地方修饰变量,而且被global修饰的变量直接被标识为全局变量,对该变量修改会影响全局变量的值,但不影响函数中未被global修饰的同名变量(依然是局部变量),nonlocal只能在嵌套函数(可能还有其他的地方,我还没有检查)中使用,用于标识嵌套函数中的变量是包含该嵌套函数的函数中的同名变量,在嵌套函数中修改变量会影响函数中的变量。如果在函数中使用global修饰了变量,那么在嵌套函数中用nonlocal修饰同名变量会发生报错,因为nonlocal表示该变量在函数中已经定义,但检查时因为同名变量被global修饰为全局变量,所以不存在同名的局部变量,从而导致错误

转载 Python中关键字global与nonlocal的区别的更多相关文章

  1. Python中关键字global与nonlocal的区别

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/xCyansun/article/details/79672634终于下定决心学习Python了.既然 ...

  2. python 作用域,global与nonlocal的区别

    在Python中并不是所有的语句块中都会产生作用域.只有当变量在Module(模块).Class(类).def(函数)中定义的时候,才会有作用域的概念. 如果在函数中要对全局变量做改变可以使用glob ...

  3. Python中的global和nonlocal

    在Python中,一个变量的scope范围从小到大分成4部分:Local Scope(也可以看成是当前函数形成的scope),Enclosing Scope(简单来说,就是外层函数形成的scope), ...

  4. python中全局global和局部nonlocal命名空间

    python中全局global和局部nonlocal命名空间 局部名称空间对全局名称空间的变量可以引用,但是无法改变. count = 1 def func1(): count = 2 print(c ...

  5. python中import和from...import...的区别

    python中import和from...import...的区别: 只用import时,如import xx,引入的xx是模块名,而不是模块内具体的类.函数.变量等成员,使用该模块的成员时需写成xx ...

  6. 简述C#中关键字var和dynamic的区别

    C#中关键字var和dynamic的区别如下: 1.var申明的变量必须初始化,dynamic申明的变量无需初始化. 2.var关键字只能在方法内部申明局部变量,dynamic关键字可用于局部变量,字 ...

  7. 转发 python中file和open有什么区别

    python中file和open有什么区别?2008-04-15 11:30地痞小流氓 | 分类:python | 浏览3426次python中file和open有什么区别?都是打开文件,说的越详细越 ...

  8. Python中str()与repr()函数的区别——repr() 的输出追求明确性,除了对象内容,还需要展示出对象的数据类型信息,适合开发和调试阶段使用

    Python中str()与repr()函数的区别 from:https://www.jianshu.com/p/2a41315ca47e 在 Python 中要将某一类型的变量或者常量转换为字符串对象 ...

  9. python中的关键字global和nonlocal

    知识点: global将一个变量变为全局变量 nonlocal改变最近的变量,又不是全局作用. 1.global 在python中,当引用一个变量的时候,对这个变量的搜索按找本地作用域(Local). ...

随机推荐

  1. C# 导出dataGridView中的值到Excel

    C# 怎么导出dataGridView中的值到Excel 1 2 3 4 5 6 在系统应用过程中,数据是系统的核心.如果直接在应用软件中看数据,有时也有些不便,所以就会把系统数据转换成Excel格式 ...

  2. Java学习笔记(十四):java常用的包

  3. python 网络内容: 初识socket

    一 C\S架构,客户端服务端架构 客户端(client) : 享受服务端提供的服务 服务端(server) : 给客户端提供服务 B\S 浏览器和服务端 B(browser) 二 网络通信的整个流程( ...

  4. 二叉搜索树与双向链表(python)

    题目描述 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. # -*- coding:utf-8 -*- # class TreeNo ...

  5. easyui combobox下拉框文字超出宽度有横向滚轮

    //下拉框显示横向滚轮 $(".combo").mouseenter(function(){ $(this).prev().combobox("showPanel&quo ...

  6. [转贴]LTP--linux稳定性测试 linux性能测试 ltp压力测试 ---IBM 的 linux test project

    https://blog.csdn.net/melody157398/article/details/24354415   LTP--linux稳定性测试 linux性能测试 ltp压力测试 ---I ...

  7. 彻底关闭win10后台同步数据(转自技术社区)

    设置隐私里面关闭所有同步数据选项 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\将下面子项属性修改 OneSyncSvc的start属相修改 ...

  8. java 线程池简单例子

    package com.hra.riskprice; import com.hra.riskprice.SysEnum.Factor_Type; import com.hra.riskprice.po ...

  9. 20175316 盛茂淞 2018-2019-2 《Java程序设计》实验一 Java开发环境的熟悉 实验报告

    20175316 盛茂淞 2018-2019-2 <Java程序设计>实验一 Java开发环境的熟悉 实验报告 一.实验要求 1.使用JDK编译.运行简单的Java程序: 2.使用IDEA ...

  10. django的简单原理

    一.自定义客户端和服务端的请求响应 1.客户端打开url,向服务器发出请求 2.服务端用socket写一个py,用于接收请求和做出响应 3.服务端接收请求 4.服务端模拟HTTP协议做出响应,状态行为 ...