1 local和global变量

先来看一个最简单的Python程序例子:

import numpy as np
n = 2
def func(a):
b = 1
return a + b print(func(n)) # 3

这里b声明在函数func内,则该变量拥有一个local scope(局部作用域,即在函数内),我们将这类变量称为local(局部)变量。

与之相对的npn这两个变量都在函数之外声明,也即它们都在gobal scope(全局作用域)中,我们将它们global(全局)变量。

如果我们使用IDE在return a+b处打断点并调试,那么可以看到IDE很方便地为我们展示了当前的局部和全局变量(以VSCode为例):

我们在local scope内也可以对global变量进行读取,如下所示:

n = 2
def func(a):
b = 1
return a + b + n # 对全局变量进行读取 print(func(n)) # 5

然而,如果在local scope内对global变量进行修改,比如这样写:

n = 2
def func(a):
n += 1 # 对全局变量进行修改
b = 1
return a + b + n print(func(n))

运行到n+=1这一语句是就会抛出异常:

UnboundLocalError: local variable 'n' referenced before assignment

此时我们需要用global关键字在局部作用域内声明一个global变量,然后就可以自由修改该变量了:

n = 2
def func(a):
global n
n += 1
b = 1
return a + b + n print(func(n)) # 6

2 nonlocal 变量

最后,我们还要提一种变量,叫nonlocal变量。这种变量常用在局部嵌套函数中将外层函数中的自由变量绑定到内层函数作用域(事实上外层函数中的自由变量对于内层函数来说既也非local也非global,故名nonlocal)。如下列所示:

# outside function
def outer():
message = 'local' # nested function
def inner(): # declare nonlocal variable
nonlocal message message = 'nonlocal'
print("inner:", message) inner()
print("outer:", message) outer()

打印输出:

inner: nonlocal
outer: nonlocal

可以看到,nonlocal的使用将外层函数作用域中的自由变量message和内层函数的作用域进行了绑定。

不过需要注意的是,如果我们使用global关键字来声明变量:

# outside function
def outer():
message = 'local' # nested function
def inner(): # declare global variable
global message message = 'nonlocal'
print("inner:", message) inner()
print("outer:", message) outer()

那么最终的打印输出结果为:

inner: nonlocal
outer: local

这是因为global关键字的使用让我们在inner()函数(局部作用域)内声明了一个global变量,故如果我们在inner()函数内做任何修改,则修改的结果只会在局部作用域(也即outer()函数)之外出现。

此外,nonlocal还可以用来构建如下列所示的闭包函数func(参见我的博客《Python技法4:闭包和保存自由变量 》):

def sample():
n = 0
# 闭包函数
def func():
nonlocal n
n += 1
print("n =", n)
return func f = sample()
f() # n = 1
f() # n = 2

这里也是通过nonlocal关键字将自由变量与内层函数绑定,然后再对其进行修改的。

Python:global、local与nonlocal变量的更多相关文章

  1. [python]global与nonlocal关键字

    在Python中,当引用一个变量的时候,对这个变量的搜索是按找本地作用域(Local).嵌套作用域(Enclosing function locals).全局作用域(Global).内置作用域(bui ...

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

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

  3. python global和nonlocal的使用

    ◆global和nonlocal是Python的两个重要变量作用域关键字 1.global用在全局变量,应用场景: 变量定义在函数外部的时候,如果函数里面想改变这个全局变量的值,需要在当前的引用函数里 ...

  4. Python 3 学习笔记之——变量作用域、模块和包

    1. 变量作用域 Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的.变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称.Python 的作用域一共 ...

  5. 《疯狂Python讲义》重要笔记--变量

    一个Python解释器 接下来的旅程——你需要下载好Python,Python解释器通常放在 /usr/local/bin/python3.7 ; 在Unix系统的bash中输入 where pyth ...

  6. TLS 与 python thread local

    TLS 先说TLS( Thread Local Storage),wiki上是这么解释的: Thread-local storage (TLS) is a computer programming m ...

  7. Python基础一. 简介、变量、对象及引用

    一.Python简介 Python是一门计算机编程语言,它是由荷兰人Guido van Rossum在1989年圣诞节期间为了打发无聊的圣诞节而编写的,作为ABC语言的继承 特性: 面向对象.解释型. ...

  8. 【类不类二】Python的类变量与实例变量

    在研究类的时候,难免会有很多疑问,C论坛和博客园高手如云(不知道是不是也美女如云), 搜到了这篇博文,是介绍Python的类变量和实例变量的 ! 刚好在下对self.***这种形式的实例变 量不是很理 ...

  9. Python基础-类变量和实例变量

    Python基础-类变量和实例变量 写在前面 如非特别说明,下文均基于Python3 大纲: 1. 类变量和实例变量 在Python Tutorial中对于类变量和实例变量是这样描述的: Genera ...

  10. Python入门学习:1.变量和简单的数据类型

    python入门学习:1.变量和简单的数据类型 关键点:变量.字符串.数字 1.1 变量的命名和使用1.2 字符串1.3 数字1.4 注释 1.1 变量的命名和使用   变量,顾名思义是一个可变的量, ...

随机推荐

  1. OpenHarmony 3.2 Release新特性解读之驱动HCS

      OpenAtom OpenHarmony(以下简称"OpenHarmony")开源社区,在今年4月正式发布了OpenHarmony 3.2 Release版本,标准系统能力进一 ...

  2. OpenHarmony标准系统开机时长优化

    简介 万物互联时代,产品性能至关重要,而系统启动时间是系统性能的重要组成部分,因为用户必须等待系统启动完成后才能使用设备.对于经常需要进行冷启动的汽车等设备而言,较短的启动时间至关重要(没有人喜欢在等 ...

  3. Java 继承与多态:代码重用与灵活性的巧妙结合

    Java 继承(子类和超类) 在 Java 中,可以从一个类继承属性和方法到另一个类.我们将"继承概念"分为两类: 子类(child): 从另一个类继承的类 超类(parent): ...

  4. 【Learning eBPF-3】一个 eBPF 程序的深入剖析

    从这一章开始,我们先放下 BCC 框架,来看仅通过 C 语言如何实现一个 eBPF.如此一来,你会更加理解 BCC 所做的底层工作. 在这一章中,我们会讨论一个 eBPF 程序被执行的完整流程,如下图 ...

  5. 【Insights直播】华为帐号服务,打造全场景安全帐号体系

    在App运营过程中,如何保持用户增长和提升用户体验始终是开发者关注的问题,而作为用户使用体验感知的第一环节--帐号注册登录环节是不可忽视,且有很大提升空间的.如何提升帐号的注册登录体验?如何保证用户在 ...

  6. std::string 拼接字符串

    #include <iostream> #include <string> #include <sstream> int main() { // 方法一:12345 ...

  7. 生成 MFC ActiveX (OCX)时,报错:MSB801:未能注册输出

    我们在生成 ocx 控件时,报错:MSB801:未能注册输出,如下图: 解决方法: 1.打开 项目属性 -> 链接器 -> 常规  :  逐用户重定向 改为  是 2. 重新生成 如果此时 ...

  8. 动态库 DLL 封装二:dll封装方法

    例:我新建的工程是,带lib的MFC规则的DLL 主要有三个文件需要写东西 ( .h /  .cpp  /  .def ) 示例: // a.h ...... #ifdef __cplusplus e ...

  9. centos8 \CentOS 9 Stream rpm 安装mysql8.0.28

    centos8 rpm 安装mysql8.0.28 检查 检测系统是否自带安装 MySQL 命令如下: rpm -qa | grep mysql 如果如下存在已安装的包,就需要卸载 mysql80-c ...

  10. jenkins 持续集成和交付——pipeline(五)

    前言 整理一下pipeline. 正文 介绍 什么是pipeline呢? 根据前面的所得,我们知道,以前都是模板形式,但是如果有些复杂的项目,需要用更加自定义的写法,那么就有了pipeline,也就是 ...