Python函数命名空间,作用域LEGB及Global详析
作者:测试工程师Jane 发布时间:2022-09-18 18:14:16
一、命名空间和作用域
当出现了函数,变量声明的位置就发生了变化,不同位置声明的变量,能访问这个变量的范围也出现了限制
1.1 定义
**命名空间:**声明定义了变量,变量存在的范围,主要是通过命名空间,来区分不同范围中声明的变量。作用域: 一个数据能够作用的范围
命名空间根据范围的不同,分为以下几种类型:
1.2 内建命名空间和内建作用域
Python程序中最大的一个命名空间,通常在解释器运行目标代码的时候(也就是点RUN的时候),由解释器创建的一个命名空间,负责初始化(即第一次赋值、第一次创建)系统环境变量。如:int/type()等
内建命名空间加载时间:运行代码之前,通过解释器加载好系统的命名空间。包含了int/float/str/type()等等各种数据类型或者函数,所以我们在代码中才可以直接使用这些数据类型或者函数
作用:初始化系统环境变量
作用域:内建作用域(Builtin),此空间内的数据作用范围是整个内建空间,包括子空间
查看方式:dir()
1.3 全局命名空间和全局作用域
定义: 编写Python代码时,创建一个python文件,其中声明在函数外部的变量,称为:全局变量(global)。当前可以声明全局变量的所有位置称为全局命名空间
加载时间:解释器运行目标代码时,加载全局命名空间,初始化该命名空间中的所有全局变量作用:声明、定义全局变量的范围作用域:全局作用(Global)查看方式:globals()查看当前全局命名空间中的所有全局变量,本质上globals()就是一个存储了数据的字典,
例如:
name = "张三"
age = 12
grade = ["1",2,"3"]
def outer():
a = "a"
def inner():
a = "b"
return inner
fun = outer()
fun()
print(f"全局变量字典为:{globals()}")
运行结果:
1.3 局部命名空间和局部作用域
定义:当Python文件中声明函数时,独立出来了一个小的作用范围(函数内部),通常情况下我们将函数内部的空间称为:局部命名空间
加载时间:解释器运行目标代码时,加载完全局命名空间之后,加载局部命名空间,初始化局部命名空间中的局部变量
注意:如果是嵌套函数,嵌套函数是没有命名空间的,嵌套函数的空间存于父函数内,但嵌套函数是有其自己的作用域的,叫嵌套作用域(内部作用域)
作用:声明、定义局部变量作用域:局部作用域(嵌套作用域)查看方式:Locals()查看当前命名空间中的所有数据
Locals(): 查看当前命名空间中的数据
编写在函数内部:查看局部命名空间中的数据编写在函数外部:和globals()一样的意义
示例:
name = "张三"
age = 12
grade = ["1",2,"3"]
def outer():
a = "a"
print(f"outer局部的数据:{locals()}")
def inner():
a = "b"
print(f"inner局部的数据:{locals()}")
return inner
fun = outer()
fun()
print(f"全局变量字典为:{globals()}")
print(f"全局部的数据:{locals()}")
运行结果:
1.4 总结
命名空间是一个名词, 表示了一个可以声明变量的范围
用作域是一个动词,表示一个变量起作用的范围
解释器运行时,命名空间的加载顺序:内建命名空间–>全局命名空间–>局部命名空间
查询使用变量,查询使用顺序:内部作用域–>嵌套作用域–>全局作用域–>内建作用域,也就是Python常说的LEGB原则。查找顺序通俗的说就是:就近原则,一直找到内建作用域,找不到报:“name is not defined”
1.5 扩展LEGB
Local,本地作用域,局部作用域的local命名空间。函数调用时创建,调用结束消亡
Enclosing,Python2.2时引入嵌套函数,实现了闭包,这个就是嵌套函数的外部函数的命名空间
Global,全局作用域,即一个模块的命名空间。模块被import时创建 ,解释器退出时消亡
Build-in,内置模块的命名空间,生命周期从python解释器启动时创建到解释器退出时消亡,例如:print(open),print和open都是的变量
二、Global关键字的使用说明
在讲述什么是Global之前,让我们先来看一个例子,以下例子两条print语句分别打印什么:
x = 100
def fn1():
x +=1
print(f"函数内的{x}")
fn1()
print(f"变更后的{x}")
运行结果:
为什么会运行报错:X在使用前需要先分配变量值,明明我们在全局已经定义了一个X=100
原因:在python动态语言内,== 赋值即定义== ,在inner内部
x += 1其实是一个x = x+1的赋值语句,那这个x就会函数运行在初始化进行加载,变成局部的一个变量
而=运算时,从左往右执行,在x=的时候已经默许了x是local variable,因此外部作用域的x=100是被屏蔽的。所以x+1中的x相当于一个没有赋值的变量,从而报错。
那么怎么解决这个问题?解决的办法一:使用global关建字将x定义为全局变量,这时在函数局部就会将x指向全局的变量x
让我们来看看具体的应用,下面的代码运行结果如何:
x = 100
def fn1():
x = 10
global x
x +=1
print(f"函数内的{x}")
fn1()
print(f"变更后的{x}")
运行结果:
为什么还是报错,我们不是已经使用了global吗?那是因为我们前面声明前加了一句:x = 10
x = 10 时会将其置为局部变量,但程序执行到global x时,发现x已经在局部定义过了,所以报错,所以我们要先声明再调用
所以我们将程序调整为:
那么问题又来了,下面的例子,global x在inner函数内可以调用吗?
x = 100
def outer():
global x
x +=1
print(f"ouer的x调用结果{x}")
def inner():
x +=1
print(f"inner的x调用结果{x}")
return inner
a = outer()
a()
运行结果:
为什么报错,不是已经定义了global全局变量,同时也是局部作用域内先定义了吗?
原因:Global 定义只在全局和定义的当前作用域内起作用,所以上面的例子,global x只在全局作用域和嵌套作用域内可用,如果inner内部想调用,需要做以下调整
特别说明:
global关键字是一种破坏函数封装的方式,变量未经过传参即可在函数内部作用域内使用。所以在日常使用中,**不要使用,那我们要实现这种调用,可以用什么方式呢?python给我提供了一个关键字:Nolocal,后续我的笔记中会详细提到
来源:https://blog.csdn.net/totorobig/article/details/126687921


猜你喜欢
- 前言在我们往数据库插入数据的时候,需要判断某个字段是否存在,如果存在则执行更新操作,如果不存在则执行插入操作,如果每次首先查询一次判断是否存
- 简介这篇宏哥就带着小伙伴们分享一下如何连接模拟器(电脑版的虚拟手机),然后再安装一款APP-淘宝为例。一、appium+pycharm+连接
- 如何在Mac中配置Python虚拟环境1.安装virtualenvpip3 install virtualenv2.安装virtualenv
- 前言NumPy(Numerical Python)是Python的一种开源的数值计算扩展。这种工具可用来存储和处理大型矩阵,比Python自
- Python的安装并不难,但是要正确安装它的库以及配置环境变量则有些麻烦。对于刚刚开始想要学习Python的小伙伴来说,用Anaconda这
- 原来的题目设想为界面视觉效果的统一性,但是“统一”这个词似乎有点敏感,怕触动萌点无数,而我也无意去设定一个什么什么的统一性来侃侃而谈,极为专
- 先看看CSS框架的利与弊前段时间一直在讨论CSS框架。很多朋友看了那三篇文章后提了不少自己意见。特别是一位北京的朋友A君,他有一个小的团体,
- 一 概述Python生态系统的一些核心基础数据分析库:NumPy:支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库,包含
- 刚才运行了一段代码,来查看Request.ServerVariables里面有多少值,看了一下,共50个!代码<%=Request.S
- 在MySQL中,如何实现Top N及M至N段的记录查询?我们可以利用MySQL中SELECT支持的一个子句——LIMIT——来完成这项功能。
- 什么是模式前阵子准备期末考试,劳神又伤身的,实在闲不得空来更新文章,今天和大家说说javascript中的设计模式。首先呢,我们需要知道的是
- opencv读取图像为b,g,r方法,比如img = cv2.imread("xx.jpg")cv2.imshow(&q
- 用python做大型工程时,经常会出现import问题。比如,当你import另一个py文件时,这个py不存在于你的运行路径下,便会报错。大
- 问题现象从阿里云上镜像过来的一台数据库服务器,SQL Agent服务启动不了,提示服务启动后停止。(原数据库服务器是正常的,怀疑跟镜像有关)
- 第一种方法:这个是删除单字段图片的代码。比较简单,因为图片字段已经预先存在数据库表的bookpic的字段里面了。 代码如下: <!-
- 实际上face_recognition这个项目尤其是dlib更适用于Linux系统。经过我的测试,在性能方面,编译同样规格的项目,这个工具在
- window对象表示浏览器中打开的窗口,提供关于窗口状态的信息。可以用window对象访问窗口中绘制的文档、窗口中发生的事件和影响窗口的浏览
- 如下所示:import matplotlib.pyplot as pltimport numpy as npa = np.array([1,
- 诊断SQLSERVER问题常用的日志这里主要有两个:(1)Windows事件日志(2)SQLSERVER ErrorLog1、Windows
- 读取图片并将二进制数据转换成base64格式首先,使用nodejs进行数据读取,需要用到nodejs的fs模块进行数据读取:fs.readF