# 参数类型与默认值

URL: https://caijiao.org/python/ch05/parameters
Source: docs/python/ch05/parameters.md
Description: 本章节介绍 Python 中函数的参数类型和默认值的使用，包括如何设置默认参数值、使用类型注解以及常见的应用场景，帮助你更好地理解函数参数的灵活性与安全性。

在 [Python](/python/) 中，函数的参数可以具备不同的类型，并且可以设置默认值。了解参数类型和默认值的使用，可以让你编写更加灵活和安全的函数。

## 参数类型

Python 是一种动态类型语言，意味着你不需要显式地声明变量的类型。函数的参数也可以是任何类型，包括基本数据类型、容器类型、函数、类等。

### 类型注解

Python 3 引入了类型注解（Type Hinting）功能，允许你为函数参数和返回值指定类型，这有助于提高代码的可读性和可维护性。

```python
def add(a: int, b: int) -> int:
    return a + b
```

在上述代码中，`a` 和 `b` 被注解为 `int` 类型，`-> int` 表示该函数的返回值类型为 `int`。

### 类型检查与静态分析

类型注解本身并不会强制执行类型检查，Python 仍然是动态语言。如果你想进行类型检查，可以使用像 `mypy` 这样的工具进行静态类型分析。

```bash
$ pip install mypy
$ mypy your_script.py
```

## 默认参数值

在函数定义时，你可以为参数设置默认值，如果调用函数时没有提供该参数的值，则使用默认值。默认值的参数必须放在没有默认值的参数后面。

```python
def greet(name: str = "Guest"):
    print(f"Hello, {name}!")

greet()           # Hello, Guest!
greet("Alice")    # Hello, Alice!
```

### 使用默认参数的注意事项

当你为参数设置默认值时，确保这些默认值是常量或可变对象（如列表或字典）时要特别小心，因为在函数调用时它们的修改可能会影响之后的调用。

```python
def add_item(item, list_items=[]):
    list_items.append(item)
    return list_items

print(add_item(1))    # [1]
print(add_item(2))    # [1, 2]
```

上述代码中，`list_items` 是一个可变类型的默认值。每次调用 `add_item()` 时，如果没有传入 `list_items`，它会使用同一个列表对象，导致后续调用共享同一个列表。为避免这个问题，应该使用 `None` 作为默认值，并在函数体内初始化一个新的列表。

```python
def add_item(item, list_items=None):
    if list_items is None:
        list_items = []
    list_items.append(item)
    return list_items
```

## 可变参数与默认值

可变参数 `*args` 和 `**kwargs` 也可以与默认值一起使用，进一步增强函数的灵活性。

```python
def greet(message="Hello", *names):
    for name in names:
        print(f"{message}, {name}!")

greet("Hi", "Alice", "Bob")  # Hi, Alice! Hi, Bob!
greet("Welcome", "Tom")      # Welcome, Tom!
```

在上面的例子中，`message` 有默认值 `"Hello"`，而 `*names` 是一个可变参数，用于接收不定数量的名字。

## 总结

- **类型注解**：Python 支持为函数的参数和返回值添加类型注解，有助于代码的静态检查和可维护性。
- **默认参数值**：可以为函数的参数设置默认值，当函数调用时没有传递该参数时使用默认值。要注意可变类型默认值的问题。
- **可变参数与默认值**：可以结合使用 `*args` 和 `**kwargs`，与默认值一起增强函数的灵活性。

掌握参数类型和默认值的使用，可以帮助你编写更具可读性、可维护性和健壮性的 Python 代码。
