变量作用域
在 Python 中有作用域的概念,但不是所有变量都是全局变量。Python 的作用域规则与其他语言有些不同,特别是关于块级作用域的处理。让我详细解释一下:
Python 的作用域层次(LEGB 规则)
L - Local(局部作用域):
- 在函数内部定义的变量
- 只在函数内部可见
E - Enclosing(闭包作用域):
- 嵌套函数中的外层函数作用域
- 适用于闭包情况
G - Global(全局作用域):
- 在模块级别(文件顶层)定义的变量
- 整个文件可见
B - Built-in(内置作用域):
- Python 内置函数和变量(如
print,len)
- Python 内置函数和变量(如
关键区别:没有块级作用域
Python 没有像 C/C++/Java 那样的块级作用域(block scope)。这意味着:
1 | |
同样适用于:
1 | |
与全局变量的区别
1 | |
为什么人们会误解?
函数创建新作用域:
1
2
3def func():
y = 20
print(y) # 报错!y 只存在于函数作用域内类创建新作用域:
1
2
3
4class MyClass:
z = 30
print(MyClass.z) # 正确(通过类访问)
# print(z) # 报错!z 不是全局变量赋值会改变作用域:
1
2
3
4x = 10
def func():
print(x) # 访问全局 x
x = 20 # 这会将 x 变为局部变量!
作用域陷阱:global 和 nonlocal
1 | |
总结表格
| 代码结构 | 是否创建新作用域 | 示例 |
|---|---|---|
| 模块(文件) | ? 全局作用域 | global_var = 1 |
| 函数定义 | ? 局部作用域 | def f(): local = 2 |
| 类定义 | ? 类作用域 | class C: cls_var = 3 |
if/for/while/with |
? 不创建新作用域 | if True: var = 4(仍在当前作用域) |
| 列表推导式 | ? Python 3+ 有独立作用域 | [x for x in range(5)] 后 x 未定义 |
所以回到你的原始问题:在 with 块中定义的变量能在外部使用,正是因为 Python 没有块级作用域,但不等于所有变量都是全局变量。变量的作用域取决于它被定义的位置(函数内、类内、模块内),而不是它所在的代码块类型。
变量作用域
https://mingzaitown.github.io/2025/10/29/python/Python基本语法/变量作用域/