看一看,Python这四种作用域你都知道吗?
myzbx 2025-07-17 22:54 3 浏览
点赞、收藏、加关注,下次找我不迷路
一、啥是作用域?先打个比方
比如说,你在自己的卧室(相当于一个小空间)里放了一本书,这本书在卧室里随便你怎么看,这就是这本书在卧室这个 "作用域" 内有效。但如果你走到客厅(另一个空间),想找这本书就找不到了,因为它的作用域只在卧室。在 Python 里,作用域其实就是变量能够被访问的范围,也就是变量的 "活动范围"。
二、Python 作用域的四种类型
Python 中有四种作用域,分别是局部作用域(Local)、全局作用域(Global)、嵌套作用域(Enclosing)和内置作用域(Built - in)。接下来咱们一个一个详细说,每个都配上简单的例子。
(一)局部作用域(Local)
局部作用域就像是一个 "小圈子",一般指的是函数内部的作用域。在函数里面定义的变量,只能在这个函数里面用,出了这个函数,就像从这个小圈子里出去了,就找不到这个变量了。
def my_function():
local_var = 10 # 这是局部变量,只在my_function函数里有效
print("函数内局部变量:", local_var)
my_function() # 输出:函数内局部变量:10
# print(local_var) # 这行代码会报错,因为local_var在函数外不存在
就好比你在自己的小房间(函数)里养了一只宠物,这只宠物只在你的小房间里活动,出了房间就看不到它了。
(二)全局作用域(Global)
全局作用域就像是一个 "大广场",在整个文件(模块)中都有效,也就是说,在函数外部定义的变量,整个文件里的函数都可以访问它(但要注意修改的问题,后面会讲)。
global_var = 20 # 这是全局变量,在整个文件中有效
def my_function1():
print("函数1访问全局变量:", global_var)
def my_function2():
print("函数2访问全局变量:", global_var)
my_function1() # 输出:函数1访问全局变量:20
my_function2() # 输出:函数2访问全局变量:20
这就相当于广场上有一个公共设施,不管你在广场的哪个角落(哪个函数),都能看到并使用它。
(三)嵌套作用域(Enclosing)
嵌套作用域是指在一个函数里面再定义一个函数,里面的函数(内层函数)可以访问外层函数定义的变量,但外层函数不能访问内层函数的变量。这就像是一层套一层的盒子,内层盒子可以看到外层盒子里的东西,外层盒子看不到内层盒子里的东西。
def outer_function():
outer_var = 30 # 外层函数的变量
def inner_function():
inner_var = 40 # 内层函数的变量
print("内层函数访问外层变量:", outer_var) # 可以访问外层变量
inner_function()
# print(inner_var) # 这行代码会报错,外层函数不能访问内层变量
outer_function() # 输出:内层函数访问外层变量:30
就像你在一个大盒子里放了一个小盒子,小盒子能看到大盒子里的东西,但大盒子看不到小盒子里的东西。
(四)内置作用域(Built - in)
内置作用域是 Python 预先定义好的作用域,里面包含了所有的内置函数和内置变量,比如 print、len、list 等,在整个程序中都可以直接使用,不需要额外定义。
print("内置函数len的使用:", len([1, 2, 3])) # 直接使用内置函数len,输出3
这就好比 Python 给我们准备了一套 "通用工具",我们在任何时候都可以拿过来用。
为了让大家更清楚地对比这四种作用域,咱们做个表格:
作用域类型 | 定义位置 | 有效范围 | 示例 |
局部作用域(Local) | 函数内部 | 仅在函数内部 | def f(): a=10 |
全局作用域(Global) | 函数外部 | 整个文件(模块) | b=20def f(): print(b) |
嵌套作用域(Enclosing) | 外层函数内部 | 外层函数及内层函数 | def outer(): c=30 def inner(): print(c) |
内置作用域(Built - in) | Python 内置 | 整个程序 | print(len([1,2,3])) |
三、变量查找顺序:LEGB 原则
当我们在代码中使用一个变量时,Python 会按照 LEGB 的顺序来查找变量,LEGB 就是这四种作用域英文首字母的缩写,顺序是:Local(局部作用域)→ Enclosing(嵌套作用域)→ Global(全局作用域)→ Built - in(内置作用域)。也就是说,先在当前的局部作用域找,如果找不到,就到外层的嵌套作用域找,再找不到就到全局作用域找,最后到内置作用域找,如果都找不到,就会报错。
built_in_var = "内置变量" # 内置作用域其实是Python预定义的,这里只是模拟
global_var = "全局变量"
def outer():
enclosing_var = "嵌套作用域变量"
def inner():
local_var = "局部变量"
print(local_var) # 先找局部作用域,找到,输出:局部变量
print(enclosing_var) # 局部没有,找嵌套作用域,找到
print(global_var) # 嵌套没有,找全局作用域,找到
print(built_in_var) # 全局没有,找内置作用域(这里模拟的,实际内置作用域是Python自带的)
inner()
outer()
通过这个例子,大家可以清楚地看到变量查找的顺序。
四、修改全局变量和嵌套作用域变量:global 和 nonlocal 关键字
(一)修改全局变量:global 关键字
前面咱们说过,在函数内部可以访问全局变量,但如果想在函数内部修改全局变量,就需要使用 global 关键字声明,否则 Python 会认为你在函数内部定义了一个新的局部变量。
global_num = 10
def change_global():
# global global_num # 不声明的话,下面这行代码会报错
global_num = 20 # 报错,因为没有声明global,Python认为这是局部变量赋值,而之前没有定义这个局部变量
# change_global() # 运行会报错
# 正确的做法:
def change_global_correct():
global global_num
global_num = 20
change_global_correct()
print(global_num) # 输出:20
就像你想修改广场上的公共设施,得先告诉大家你要修改的是公共的,而不是自己弄一个新的。
(二)修改嵌套作用域变量:nonlocal 关键字
在内层函数中,如果想修改外层函数的变量,需要使用 nonlocal 关键字声明,否则会被认为是在内层函数中定义了一个新的局部变量。
def outer_nonlocal():
outer_num = 30
def inner_nonlocal():
# nonlocal outer_num # 不声明的话,下面这行代码会报错
outer_num = 40 # 报错,因为没有声明nonlocal,Python认为这是内层函数的局部变量赋值
# inner_nonlocal() # 运行会报错
# 正确的做法:
def inner_nonlocal_correct():
nonlocal outer_num
outer_num = 40
inner_nonlocal_correct()
print("修改后的外层变量:", outer_num) # 输出:修改后的外层变量:40
outer_nonlocal()
这就好比内层盒子想修改外层盒子里的东西,得先告诉系统自己要修改的是外层的变量,而不是自己内部的新变量。
五、这些情况需要注意
(一)局部变量和全局变量同名的情况
当局部变量和全局变量同名时,在函数内部,局部变量会覆盖全局变量,也就是说,在函数内部使用的是局部变量,函数外部使用的是全局变量。
name = "小明" # 全局变量
def say_hello():
name = "小红" # 局部变量,和全局变量同名
print("函数内:", name) # 输出:函数内:小红
say_hello()
print("函数外:", name) # 输出:函数外:小明
这就像是在小房间里有一个和广场上同名的物品,在小房间里用的是小房间里的物品,出了小房间还是用广场上的。
(二)内置作用域的变量不要轻易修改
内置作用域中的变量,比如 list、dict 等,是 Python 内置的函数或类型,不要轻易给它们赋值,否则会导致内置函数无法正常使用。
# 错误示例
list = [1, 2, 3] # 给内置函数list赋值,导致后面无法使用list()函数
new_list = list([4, 5, 6]) # 会报错,因为此时list是一个列表,不是函数
# 正确做法:不要给内置函数名赋值
(三)嵌套作用域的层数
虽然 Python 支持多层嵌套函数,但不建议写太多层嵌套,因为这样会让代码变得复杂,可读性差,也容易出现作用域相关的问题。
简单总结一下:
- 局部变量:函数内定义,函数内使用。
- 全局变量:函数外定义,整个文件可用,修改需 global。
- 嵌套作用域:内层函数可访问外层变量,修改外层变量需 nonlocal。
- 内置作用域:Python 自带,直接使用。
- 变量查找:按 L→E→G→B 的顺序找。
希望这篇文章能让你对 Python 作用域有一个清晰的认识,在编程的道路上更进一步!如果还有不明白的地方,欢迎在评论区留言哦!
相关推荐
- 资深架构师亲授,从堆栈到GC,一篇文章打通任督二脉!
-
“又双叒OOM了?”“服务半夜崩了,日志全是`java.lang.OutOfMemoryError`...”“GC停顿太长,用户投诉卡顿!”如果你也常被这些问题折磨,根本症结往往在于:你对Java...
- Java JAR 启动内存参数配置指南:从基础设置到性能优化
-
在启动Java可执行JAR文件时,合理配置JVM内存参数是保障应用稳定性和性能的关键。本文将系统讲解如何通过命令行参数、环境变量等方式指定内存配置,并结合实际场景提供优化建议。一、核心内存...
- 浏览器存储"四大家族":谁才是你的数据管家?
-
当你关闭浏览器再重新打开,登录状态为何还在?购物车商品为何不会消失?这些"记忆"背后,藏着浏览器存储的"四大家族"——Cookie、localStorage、sessi...
- SOP与SIP深度解析(sop与soic)
-
SOP(标准作业程序)与SIP(标准检验程序)是确保产品质量和生产效率的两大支柱,分别聚焦于生产执行和质量验证。一、核心区别:目标与作用域维度SOP(标准作业程序)SIP(标准检验程序)定位指导“如何...
- Java 技术岗面试全景备战!从基础到架构的系统性通关攻略分享
-
Java技术岗的面试往往是一项多维度的能力检验。本文将会从核心知识点、项目经验到面试策略,为你梳理一份系统性的备战攻略!需要的同学可以私信小编【学习】一、技术基础:面试的“硬性指标”1.最重要的还是...
- C++11 新特性(c++11新特性 pdf)
-
一、核心语言革新移动语义与右值引用通过&&标识临时对象(右值),实现资源转移而非复制。例如移动构造函数将原对象资源指针转移后置空,避免深拷贝,极大优化容器操作性能。12类型推导auto:自动推导变量类...
- 2026年前每个开发者都应该学习的技能
-
优秀开发者和伟大开发者之间的差距正在快速扩大。随着AI工具的爆炸式增长、自动化工作流程和日益复杂的技术栈,开发者不能再仅仅"知道如何编码"了。在2026年及以后,您的优势不仅仅是编写代...
- 看一看,Python这四种作用域你都知道吗?
-
点赞、收藏、加关注,下次找我不迷路一、啥是作用域?先打个比方比如说,你在自己的卧室(相当于一个小空间)里放了一本书,这本书在卧室里随便你怎么看,这就是这本书在卧室这个"作用域"内...
- 抛弃立即执行函数 (IIFE),拥抱现代 JavaScript 块级作用域
-
IIFE(ImmediatelyInvokedFunctionExpression)曾是JavaScript开发中的重要工具,但随着ES6+的块级作用域特性,我们现在有了更优雅的替代...
- 2025 年是时候重新认识 Symbol 的八大特性了?
-
大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!1.什么是Symbol原始类型在J...
- 函数、表达式与控制流:Rust 的核心语法构建块
-
在上一篇中我们了解了变量与类型,本篇将深入函数、表达式与控制流的使用,让你的代码更具逻辑性。一、函数定义与调用函数是组织和复用代码的基本单元。在Rust中,使用fn关键字定义函数:///计算...
- 所有权、借用与生命周期:理解 Rust 的核心机制
-
上一篇我们学习了函数、表达式和控制流,这一篇将正式进入Rust最核心、最独特的语言机制:所有权系统。一、为什么需要所有权机制?在C/C++中,内存管理依赖开发者手动操作,容易出现野指针、重复...
- Rust 语言的借用规则:构筑安全内存管理体系的核心保障机制
-
前言在系统级编程范畴内,内存安全始终是一项极具挑战性的关键议题。Rust语言凭借其独树一帜的「借用规则」(BorrowingRules),于编译阶段便有效规避了诸如空指针、野指针以及数据竞争等一系...
- 函数编写指南:参数、返回值与作用域实战详解
-
你是否在编写函数时遇到过参数传递混乱、返回值逻辑不清晰,或者变量作用域导致的奇怪bug?别担心,这篇文章将用最通俗的语言和实战案例,带你彻底搞懂函数的核心三要素:参数、返回值与作用域。一、参数:灵活...
- 服务器频繁报错?5 步教你快速排查修复!运维必看!
-
服务器突然报错、网站打不开、数据库连不上……这些问题是不是让你头大?别慌!今天教你一套「望闻问切」的排查法,90%的服务器故障都能轻松解决!一、定位错误类型:先看日志再动手1.日志是关键系统日志...
- 一周热门
- 最近发表
- 标签列表
-
- HTML 简介 (30)
- HTML 响应式设计 (31)
- HTML URL 编码 (32)
- HTML Web 服务器 (31)
- HTML 表单属性 (32)
- HTML 音频 (31)
- HTML5 支持 (33)
- HTML API (36)
- HTML 总结 (32)
- HTML 全局属性 (32)
- HTML 事件 (31)
- HTML 画布 (32)
- HTTP 方法 (30)
- 键盘快捷键 (30)
- CSS 语法 (35)
- CSS 轮廓宽度 (31)
- CSS 谷歌字体 (33)
- CSS 链接 (31)
- CSS 定位 (31)
- CSS 图片库 (32)
- CSS 图像精灵 (31)
- SVG 文本 (32)
- 时钟启动 (33)
- HTML 游戏 (34)
- JS Loop For (32)