# 变量作用域与生命周期

URL: https://caijiao.org/python/ch05/scope
Source: docs/python/ch05/scope.md
Description: 本章讲解 Python 中变量的作用域与生命周期，涵盖局部变量、全局变量、作用域规则及变量的创建与销毁时机，帮助你编写更清晰可靠的程序结构。

在编写 [Python](/python/) 程序时，理解变量的作用域（Scope）和生命周期（Lifetime）非常重要。它决定了变量在哪些位置可用、何时创建、何时被销毁。掌握这些概念有助于你避免命名冲突、调试错误和管理内存。

## 1. 什么是作用域？

作用域指变量在程序中可见和可访问的范围。Python 中变量的作用域分为以下几种：

- **局部作用域（Local）**
- **闭包作用域（Enclosing）**
- **全局作用域（Global）**
- **内建作用域（Built-in）**

这四层作用域被称为 **LEGB** 规则，是 Python 查找变量的顺序。

### 示例：LEGB 规则

```python
x = "global"

def outer():
    x = "enclosing"

    def inner():
        x = "local"
        print(x)  # 输出 local

    inner()

outer()
```

Python 会首先在局部作用域查找变量，其次是闭包作用域，再是全局作用域，最后是内建作用域。

## 2. 局部变量与全局变量

### 局部变量

局部变量在函数内部定义，仅在函数内部有效。

```python
def greet():
    message = "Hello"
    print(message)

greet()
# print(message)  # 报错：message 未定义
```

### 全局变量

全局变量在函数外部定义，可被整个模块访问。

```python
name = "Python"

def show_name():
    print(name)

show_name()  # 输出：Python
```

### 使用 `global` 修改全局变量

```python
count = 0

def increment():
    global count
    count += 1

increment()
print(count)  # 输出：1
```

## 3. `nonlocal` 关键字

当你希望修改嵌套函数中外层函数的变量时，可使用 `nonlocal` 关键字。

```python
def outer():
    x = 10
    def inner():
        nonlocal x
        x += 1
    inner()
    print(x)

outer()  # 输出：11
```

## 4. 变量的生命周期

生命周期指变量从创建到销毁的整个过程。

- 局部变量在函数调用时创建，函数结束时销毁。
- 全局变量在程序开始时创建，程序结束时销毁。

### 示例：变量生命周期

```python
def test():
    a = 100  # a 在函数开始时创建
    print(a)

test()
# a 在 test() 执行结束后被销毁
```

### 垃圾回收

Python 使用引用计数机制自动管理内存。当变量不再被引用时，解释器会自动释放内存。

## 5. 命名空间补充说明

命名空间是变量名与对象的映射表。Python 会根据作用域查找变量名所在的命名空间：

- 局部命名空间（函数内部）
- 全局命名空间（模块级）
- 内建命名空间（如 `len()`、`print()`）

你可以使用内建函数 `globals()` 和 `locals()` 查看当前命名空间的内容。

```python
x = 5
def func():
    y = 10
    print(globals())  # 包含 x
    print(locals())   # 仅包含 y

func()
```

## 总结

- Python 按照 LEGB 规则查找变量。
- 使用 `global` 和 `nonlocal` 可在不同作用域中修改变量。
- 局部变量生命周期短，全局变量贯穿程序始终。
- 理解变量作用域与生命周期有助于编写结构清晰、无副作用的代码。
