python之名称空间和作用域(关键字:global和nonlocal的使用)

news2024/11/14 2:53:13

文章目录

  • 前言
  • 1、名称空间和作用域
    • 1.1 引言
    • 1.2 名称空间
      • 1.2.1 内置名称空间
      • 1.2.2 全局名称空间
      • 1.2.3 局部名称空间
      • 1.2.4 名称空间的产生和销毁顺序
    • 1.3 作用域
      • 1.3.1 全局作用域
      • 1.3.2 局部作用域
      • 1.3.3 名字的查找顺序
    • 1.4 关键字:global
    • 1.5 关键字:nonlocal

前言

本篇文章主要讲解python中的名称空间和作用域,以及他们之间的联系,从底层出发了解其本质,理论知识偏多,请大家耐心观看。

1、名称空间和作用域

1.1 引言

我们在日常保存文件的时候,通常会遇到同名覆盖的问题,那么如何解决这个问题呢?

  1. 更改文件的名字
  2. 将同名文件放入不同的路径,也就是换个文件夹

总的来说,将文件放入不同的空间去保存,就可以避免同名覆盖的现象;那么在python中我们是如何避免这个问题的呢?

案例:

a = 1
a = 2 
print(a) # 输出结果:2,被第二个变量 a 覆盖了

def test1(b): # 形参:b
    print(b)

def b(): # 函数名:b
    pass

test1(666) # 输出结果:666

从上面可以看出,当我们定义两个 变量a时 会发生覆盖现象,而定义函数test1时使用的形参b与函数b 的名字相同,却没有发生覆盖现象,难道他们在不同空间吗?这就是本章内容需要讨论的问题了,我们接着往下看

1.2 名称空间

名称空间又称名字空间,简单来说就是存放名字的一块空间;更切确的说是存放名字和数据绑定关系的地方

  • 名称空间的意义:
    不同的空间可以存放相同的名字,名字相同不会发生冲突

  • 名称空间是对栈区的划分
    这里我们简单了下栈区是什么?大家都知道电脑在使用数据时,需要将数据从外存读取到内存,然后交由cpu来处理,而在内存中,我们又对其进行了划分,分为:
    1.、栈区:存放名字的地方,如电脑中的各种文件名
    2、 堆区:存放数据的地方,文件中的数据

视图如下:
在这里插入图片描述

  • 名称空间分为三类:
    1、内置名称空间
    2、全局名称空间
    3、局部名称空间

1.2.1 内置名称空间

伴随着python解释器的启动而产生的空间,当python解释器关闭后该空间也会被回收,因此它也是第一个被加载的空间

  • 内置名称空间的作用
    用来存放python中一些内置的名字,比如内置函数名:input、len、print 等等,这些名字不用定义就可以使用
print() # 内置函数,不用定义直接使用
ah() # 没有定义过的函数,直接使用会报错

1.2.2 全局名称空间

伴随python代码的执行而产生的空间,执行完毕后就回收,是第二个被加载的空间;只要不是局部名称空间和内置名称空间定义的名字,剩下的名字都存放在全局名称空间中

如:

a = 1
if 3>1:
	b = 5
def c()
	pass
# a、b、c 都存放在全局名称空间中

1.2.3 局部名称空间

当调用函数后,运行函数内的代码从而产生的名字,就存放在局部名称空间内;该空间在调用函数时存活,函数调用完后就会回收

如:

def a(): # 定义时函数内的代码不会执行,不会产生空间
    r1 = '哈哈' 
    r2 = 66
    # r1和r2都是局部名字
    
a() # 调用后才产生局部名称空间,执行完后销毁

1.2.4 名称空间的产生和销毁顺序

  • 产生顺序
    内置名称空间》》全局名称空间》》局部名称空间
  • 销毁顺序
    局部名称空间》》全局名称空间》》内置名称空间

python解释器启动后,会占用一部分内存,在内存中的划分一个栈区来存放名称空间;如图:
在这里插入图片描述

1.3 作用域

前面所学的名称空间就是用来引出作用域;作用域也就是名字能够作用的范围

  • 作用域分为两种类型:
    1、全局作用域
    2、局部作用域

1.3.1 全局作用域

内置名称空间和全局名称空间中的名字都属于全局作用域

  • 全局作用域的特点
    1、全局存活
    在python文件中一直存在
    2、全局有效
    名字在python文件中任意位置都可以使用

案例:

a = 666 
print(a) # 输出结果:666

def b():
    print(a) # 输出结果:666
# 可以看到 变量a属于全局名字,print属于内置名字,他们都可以在全局和局部(函数)内都可以使用

1.3.2 局部作用域

局部名称空间中的名字属于局部作用域

  • 局部作用域的特点
    1、临时存活
    只在局部名称空间产生时存在,销毁后消失
    2、局部有效
    名字只在产生自己的这个局部内起作用
def b():
    a = 666 # a 是局部名字,只能在自己这个局部内使用
    print(a) # 输出结果:666
def c():
    print(a) # 只能使用自己局部内定义的名字,报错
b()
c()    
print(a) # 不能使用局部的名字,报错

1.3.3 名字的查找顺序

当python代码执行后,程序会按顺序查找定义的名字:
局部名称空间》》全局名称空间》》内置名称空间

当名字查询到后就会停止查询,若名字在上面三个空间都无法查询,程序就会报错

案例1:

b = 1
def a():
    b = 666
    print(b) # 结果:666
a() 

在上面可以看到,函数a调用后,局部名称空间产生,那么在程序会从局部开始查找,找到后就会停止查询,输出该结果

案例2:

b = 1
def a():
    print(b) # 会报错
    b = 666
a()

从上面可以看到,在全局和局部都定义了一个 变量b,所以在调用函数后,程序会从局部开始查找得到局部的 变量b,但局部的变量b定义在 print之后,我们知道变量必须先定义在使用,这就导致了报错

1.4 关键字:global

将局部空间内的名字变为全局名称空间的名字,该名字的作用域也变成了全局
语法格式:global 变量名

案例:

a = 1
def b():
    global a # 将变量a 变为全局的名字
    a = 666
b()
print(a) # 输出结果:666

从上面可以看到,本来函数内的名字与全局内的名字是互不干扰的,但使用关键字global将变量a 变为全局的名字后,a 的值就被覆盖掉了

  • global 的本质
    函数内部(局部)不能更改全局的名字,本质上是不能修改这个名字的内存地址,如果需要修改内存地址,则需要用到 global

案例1:

a = [1,2,3] # 可变数据类型
def b():
    a.append(4) # 增加一个元素,内存地址不变
b()
print(a) # 输出结果:[1,2,3,4]

案例2:

a = [1,2,3] # 可变数据类型
def b():
    a = [66,77] # 重新定义一个列表,内存地址改变
b()
print(a) # 输出结果:[1,2,3]

说明:
从上面两个案例可以看到,在案例1中函数内为全局中列表a 增加了一个元素,但内存地址不变,从而修改了全局中的名字;在案例2中 函数内重新定义一个列表,改变了 列表a 的内存地址,所以无法修改全局的名字,只有加上 globa后,才能修改成功

  • 扩展:globas()
    得到全局作用域中所有的名字,以字典的形式打印
a = 1
def b():
    global a
    a = 666
b()
print(globals()) # 打印全局作用域中所有的名字

输出结果:

{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000002375CC73DC0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'python文件的路径', '__cached__': None, 'a': 666, 'b': <function b at 0x000002375D0181F0>}

1.5 关键字:nonlocal

如果一个函数内又定义了一个函数,也就是函数的嵌套,那么最开始的函数与它嵌套的那个函数中的名字是无法互相使用修改的,因为他们在不同的局部空间内;若想使用则需要使用关键字:nonlocal,且使用时,外层函数中的名字必须存在
语法格式:nonlocal 变量名

案例:

a = 1 # 全局变量
def b():
    a = 2 # 函数b中的局部变量
    def c():
        nonlocal a # 使函数c可以修改 函数b中a的值,但无法修改全局中的变量a的值
        a = 3 # 函数c中的局部变量
    c()
    print(a) # 输出结果:3
b()
print(a) # 输出结果:1

说明:
从上面可以看到,使用 nonlocal后内层嵌套的函数 c 就可以修改外层函数b 中的变量了,但是注意,使用关键字 nonlocal时 外层函数中必须存在该变量名,且该关键字无法作用于全局变量

  • 扩展点:关键字 locals()

locals() 在全局和局部内使用后的结果不同:

  1. 全局内:得到全局作用域内所有的名字,以字典形式打印
  2. 局部内:得到局部作用域内所有的名字,以字典形式打印

案例:

a = 1
print(locals()) # 得到全局作用域内所有的名字

def b():
 	c = 666
    print(locals()) # 得到局部作用域内所有的名字
b()

输出结果:

{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000235348B3DC0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/PC_pycharm/CSDN try/基础核心语法/Day 2/1.py', '__cached__': None, 'a': 1}
{'c': 666}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1944545.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在eclipse中导入本地的jar包配置Junit环境步骤(包含Junit中的方法一直标红的解决方法)

搭建JUnit环境 下文中我用到的本地jar包可以到我上传的资源中下载&#xff0c;不需要积分 链接&#xff1a;https://download.csdn.net/download/weixin_70987470/89571891?spm1001.2014.3001.5503 一、配置环境 跟上一篇的那种方法不一样&#xff0c;直接Add to Build Path …

MySQL的表,视图,索引创建

一。创建表 1。创建Student表 mysql> create table Student(Sno int primary key auto_increment,Sname varchar(30) not null unique,Ssex varchar(2) check (Ssex 男 or Ssex 女) not null,Sage int not null,Sdept varchar(10) default 计算机 not null); 2.创建Cour…

Linux云计算 |【第一阶段】SERVICES-DAY2

主要内容&#xff1a; DNS服务基础及搭建、特殊解析(针对地址库文件&#xff1a;DNS轮询 DNS泛域名解析 DNS别名&#xff09;、缓存DNS&#xff08;全局转发forwarders&#xff09;、DNS递归迭代&#xff08;子域授权&#xff09;、DNS主从架构搭建、DNS主从数据同步 一、DNS工…

基于Element UI内置的Select下拉和Tree树形组件,组合封装的树状下拉选择器

目录 简述 效果 功能描述 代码实现 总结 简述 基于Element UI内置的Select下拉和Tree树形组件&#xff0c;组合封装的树状下拉选择器。 效果 先看效果&#xff1a; 下拉状态&#xff1a; 选择后状态&#xff1a; 选择的数据&#xff1a; 功能描述 1、加载树结构&…

Python 使用TCP\UDP协议创建一个聊天室

server端代码&#xff1a; #encodingutf-8 # 服务端代码 import socketdef server():server_socket socket.socket(socket.AF_INET, socket.SOCK_STREAM)host socket.gethostname()port 12345server_socket.bind((host, port))server_socket.listen(5)print(等待客户端连接…

如何通过一条SQL变更多个分库分表?

数据库发展到今天&#xff0c;分库分表已经不是什么新鲜话题了&#xff0c;传统的单节点数据库架构在数据量和访问频次达到一定规模时&#xff0c;会出现性能瓶颈和扩展性问题&#xff0c;而分库分表技术通过将数据分散到多个数据库实例中来分担负载&#xff0c;从而提升系统的…

粮信甄选·非凡凸现|携手中粮期货、国信证券共同见证数智交易前沿力量

近日&#xff0c;中粮期货、国信证券联合非凸科技在深圳举办了“粮信甄选&#xff0c;非凡凸现”主题机构洽谈会&#xff0c;与行业专家、私募管理人共同探讨如何推进产业与金融的深度融合&#xff0c;以及实现科技创新与生态合作的新模式。 近年来&#xff0c;国信证券始终聚…

开源物联网网关ThingsBoard IoT Gateway

前几天测试了Neuron&#xff0c;这是一个令人印象深刻的平台&#xff0c;不过它不能算是完全免费的平台&#xff0c;因为它还是有商业许可要求的&#xff0c;挺贵的&#xff0c;大几万的&#xff0c;而且它有走向闭源的趋势。所以也在寻找它的替代方案。 今天看到一个ThingsBo…

最新全新UI异次元荔枝V4.4自动发卡系统源码

简介&#xff1a; 最新全新UI异次元荔枝V4.4自动发卡系统源码 更新日志&#xff1a; 1增加主站货源系统 2支持分站自定义支付接口 3目前插件大部分免费 4UI页面全面更新 5分站可支持对接其他分站产品 6分站客服可自定义 7支持限定优惠 图片&#xff1a; 会员中心截图&…

王春城 | TPM是如何减少设备停机时间的?

在快节奏的生产环境中&#xff0c;设备停机时间无疑是每个企业都头疼的问题。它不仅影响生产效率&#xff0c;还可能造成巨大的经济损失。那么&#xff0c;有没有一种神奇的方法能够一键减少设备停机时间呢&#xff1f;答案就是--TPM&#xff08;全面生产维护&#xff09;&…

【区块链+绿色低碳】双碳数字化管控平台 | FISCO BCOS应用案例

地方政府、园区及企业实现“双碳”目标过程中存在一些挑战与难点&#xff1a; 1. 管理者难以掌握完整、准确、全面的碳排放数据进行科学决策&#xff1a;由于碳排放核算需要对数据的来源、核算方法 的规范性和采集方法的科学性有严格要求&#xff0c;当前面临碳排放数据数据采…

什么是PCB盲孔、埋孔和电镀孔?

PCB有不同类型的孔&#xff0c;根据孔贯穿PCB内外层的层次&#xff0c;孔可分为通孔、埋孔和盲孔。 如您所知&#xff0c; PCB 由堆叠在一起的铜箔层组成.这些“过孔”连接PCB上的不同电路层。它类似于具有相互连接的隧道的地下系统。如果你玩过电子游戏“超级马里奥”&#xf…

基于web的物流配送管理系统/基于客户时间窗变化的物流配送管理系统/快递配送管理系统

摘 要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&#xff0c;各行各业相继进入信息管理时代&a…

springboot集成redis之字典缓存

什么是redis的字典缓存&#xff1f; Redis的缓存是Redis内部用于存储键值对数据结构的一种基础数据结构。在Redis中&#xff0c;所有的键值对都是通过字典这种数据结构来存储的。字典在Redis中扮演着核心角色&#xff0c;因为它不仅用于数据库中的键值对存储&#xff0c;还用于…

React 学习——条件渲染、遍历循环、事件绑定

React特点&#xff1a; 声明式的设计高效&#xff0c;采用虚拟DOM来实现DOM的渲染&#xff0c;最大限度减少DOM的操作灵活&#xff0c;跟其他库灵活搭配使用JSX&#xff0c;俗称JS里面写HTML&#xff0c;JavaScript语法的扩展组件化&#xff0c;模块化&#xff0c;代码容易复用…

SQL labs-SQL注入(二)

环境搭建参考 SQL注入&#xff08;一&#xff09; 一&#xff0c;SQL labs-less2。 http://192.168.61.206:8001/Less-2/?id-1 union select 1,2,group_concat(username , password) from users-- 与第一关没什么太大的不同&#xff0c;唯一区别就是闭合方式为数字型。 二…

苹果笔记本电脑如何优化系统 苹果电脑系统优化软件哪个好 cleanmymac x怎么用

随着时间的推移&#xff0c;你可能会发现你的MacBook运行速度变慢&#xff0c;甚至在执行一些基本任务时也会感觉到卡顿。这不仅影响了工作效率&#xff0c;也大大降低了使用体验。但别担心&#xff0c;优化你的Mac系统比做早餐还简单。本文将用一种轻松的风格向你介绍7种简单易…

AI绘画入门实践|Midjourney:使用 --seed 制作情侣头像与漫画

在 Midjourney 中&#xff0c;seed 是指一个种子&#xff0c;用于生成图像时的起点或基础。 使用格式&#xff1a;--seed 获取的seed值 获取 seed 值 使用 seed 生成图像 a cute boys avatar, background with blue sky and white cloud, Ghibli Studio style, Hayao Miyazaki…

2024最新手机软件APP下载排行网站源码 软件下载站PHP源码

源码介绍 这是一款简洁蓝色的手机软件下载应用排行、平台和最新发布网站源码&#xff0c;主要包括主页、APP列表页、APP详情介绍页、新闻资讯列表、新闻详情页、关于我们等模块页面。 软件下载站PHP网站源码&#xff0c;简单的部署上线&#xff0c;访问首页安装程序&#xff…

Docker Desktop安装

0 Preface/Foreward 1 安装 1.1 运行docker安装包 安装完Docker Desktop后&#xff0c;运行Docker Desktop&#xff0c;出现WSL 2安装不完整情况&#xff0c;具体情况如下&#xff1a; 解决方法&#xff1a;旧版 WSL 的手动安装步骤 | Microsoft Learn 也可以直接下载新的安…