Python:函数中的参数类型
- [📒 Python 函数中的参数类型](#📒 Python 函数中的参数类型)
-
- 一、参数类型全景图
- [二、核心语法:`*` 和 `/`](#二、核心语法:
*和/) -
- [1. `/` --- 位置分隔符](#1.
/— 位置分隔符) - [2. `*` --- 关键字分隔符](#2.
*— 关键字分隔符) - [3. 两者结合使用](#3. 两者结合使用)
- [1. `/` --- 位置分隔符](#1.
- 三、代码示例合集
-
- 示例1:各种参数类型定义
- [示例2:LangChain/Pydantic 风格(你代码中的写法)](#示例2:LangChain/Pydantic 风格(你代码中的写法))
- [示例3:实际应用 --- API 客户端设计](#示例3:实际应用 — API 客户端设计)
- 四、为什么要有这些设计?
- 五、速查表
- 六、记忆口诀
- 七、总结
📒 Python 函数中的参数类型
Python 函数参数类型(尤其是
*和/的作用) ,重点解释二者的不同和使用。
一、参数类型全景图
Python 函数参数分为五种类型,按定义顺序排列:
| 顺序 | 参数类型 | 语法标记 | 调用方式 | 示例 |
|---|---|---|---|---|
| 1 | 位置参数 | 无 | 按位置传递 | def f(a, b) → f(1, 2) |
| 2 | 位置分隔符 | / |
之前的参数只能位置传 | def f(a, /, b) → f(1, b=2) |
| 3 | 普通参数 | 无 | 位置或关键字都行 | def f(a, b) → f(1, 2) 或 f(a=1, b=2) |
| 4 | 关键字分隔符 | * |
之后的参数只能关键字传 | def f(a, *, b) → f(1, b=2) |
| 5 | 关键字参数 | ** |
接收多余的关键字参数 | def f(**kwargs) → f(a=1, b=2) |
二、核心语法:* 和 /
1. / --- 位置分隔符
/ 之前的参数必须按位置传递,不能使用关键字。
python
def foo(a, b, /, c, d):
print(a, b, c, d)
# ✅ 正确调用
foo(1, 2, 3, 4) # a=1, b=2, c=3, d=4(全部位置传参)
foo(1, 2, 3, d=4) # a=1, b=2, c=3, d=4
# ❌ 错误调用(a、b 不能关键字传参)
foo(a=1, b=2, c=3, d=4)
# TypeError: foo() got some positional-only arguments passed as keyword arguments
2. * --- 关键字分隔符
* 之后的参数必须按关键字传递,不能使用位置。
python
def bar(a, b, *, c, d):
print(a, b, c, d)
# ✅ 正确调用
bar(1, 2, c=3, d=4) # a=1, b=2, c=3, d=4
bar(1, 2, c=3, d=4) # a、b 可以位置,c、d 必须关键字
# ❌ 错误调用(c、d 不能位置传参)
bar(1, 2, 3, 4)
# TypeError: bar() takes 2 positional arguments but 4 were given
3. 两者结合使用
python
def full(a, b, /, c, d, *, e, f):
print(a, b, c, d, e, f)
# ✅ 唯一正确的调用方式
full(1, 2, 3, 4, e=5, f=6)
# a、b: 只能位置
# c、d: 位置或关键字都可以
# e、f: 只能关键字
# ❌ 以下调用都会报错
full(a=1, b=2, c=3, d=4, e=5, f=6) # a、b 不能关键字
full(1, 2, 3, 4, 5, 6) # e、f 不能位置
三、代码示例合集
示例1:各种参数类型定义
python
def example(
pos1, pos2, # 位置参数
/, # 位置分隔符
pos_or_kw1, pos_or_kw2, # 普通参数(位置或关键字都可以)
*, # 关键字分隔符
kw1, kw2 = "default", # 强制关键字参数(可带默认值)
**kwargs # 可变关键字参数
):
print(f"pos1: {pos1}")
print(f"pos2: {pos2}")
print(f"pos_or_kw1: {pos_or_kw1}")
print(f"pos_or_kw2: {pos_or_kw2}")
print(f"kw1: {kw1}")
print(f"kw2: {kw2}")
print(f"kwargs: {kwargs}")
# 调用(唯一正确方式)
example(
1, 2, # pos1, pos2 位置传递
3, 4, # pos_or_kw1, pos_or_kw2 位置传递(也可以关键字)
kw1=5, # 强制关键字
kw2=6, # 强制关键字
extra1=7, # 被 kwargs 捕获
extra2=8 # 被 kwargs 捕获
)
示例2:LangChain/Pydantic 风格(你代码中的写法)
python
class SearchEngine:
def hybrid_search(
self,
query: str, # 位置参数
*,
collection: str, # 强制关键字
limit: int = 10, # 强制关键字(有默认值)
output_fields: list = None
):
"""
混合搜索
query: 可以位置传,也可以关键字传
collection, limit, output_fields: 只能关键字传
"""
print(f"搜索: {query}, 集合: {collection}, 限制: {limit}")
return ["result1", "result2"]
# 使用方式
engine = SearchEngine()
# ✅ 正确调用
engine.hybrid_search("你好", collection="docs", limit=5)
engine.hybrid_search(query="你好", collection="docs", limit=5)
# ❌ 错误调用
engine.hybrid_search("你好", "docs", 5)
# TypeError: hybrid_search() takes 2 positional arguments but 4 were given
示例3:实际应用 --- API 客户端设计
python
class APIClient:
def __init__(self, base_url: str, /, *, api_key: str, timeout: int = 30):
"""
base_url: 只能位置传参(因为它在 / 前面)
api_key, timeout: 只能关键字传参(因为它们在 * 后面)
"""
self.base_url = base_url
self.api_key = api_key
self.timeout = timeout
def request(
self,
endpoint: str,
/,
*,
method: str = "GET",
data: dict = None,
headers: dict = None
):
"""
endpoint: 只能位置传参
method, data, headers: 只能关键字传参
"""
print(f"请求: {endpoint}, 方法: {method}")
return {"status": 200}
# 创建客户端
client = APIClient("https://api.example.com", api_key="secret", timeout=60)
# 发起请求
client.request("/users") # ✅ endpoint 位置传递
client.request("/users", method="POST", data={"name": "Alice"}) # ✅
四、为什么要有这些设计?
| 语法 | 设计目的 | 使用场景 |
|---|---|---|
| 位置参数 | 简单高效,传递少量参数 | 参数少,含义明确(如 len(list)) |
/ (位置分隔符) |
强制位置传递,保持向后兼容 | API 设计,防止调用者因参数名变更而破坏代码 |
| 关键字参数 | 明确参数含义,不受顺序影响 | 参数多,或参数名自解释(如 search(query="...", limit=10)) |
* (关键字分隔符) |
强制关键字传递,提高可读性 | 重要参数、可选配置参数(如 model="gpt-4", temperature=0.7) |
**kwargs |
接收多余的关键字参数 | 传递配置、扩展性设计 |
五、速查表
| 你的写法 | 含义 |
|---|---|
def f(a, b) |
a、b 都可以位置或关键字传递 |
def f(a, b, /) |
a、b 只能位置传递 |
def f(*, a, b) |
a、b 只能关键字传递 |
def f(a, *, b) |
a 任意,b 只能关键字 |
def f(a, /, b) |
a 只能位置,b 任意 |
def f(a, /, *, b) |
a 只能位置,b 只能关键字 |
def f(**kwargs) |
接收所有关键字参数 |
def f(*args, **kwargs) |
接收所有位置和关键字参数 |
六、记忆口诀
"位置在前,关键字在后"
/左边:只能位置传*右边:只能关键字传- 两者之间:随便传
七、总结
| 概念 | 一句话总结 |
|---|---|
| 位置参数 | 按顺序传入 |
| 关键字参数 | 按名字传入 |
/ |
它左边的是"专用座位",只能按顺序坐 |
* |
它右边的是"指定座位",必须喊名字坐 |