Python:函数中的参数类型

Python:函数中的参数类型

📒 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) 接收所有位置和关键字参数

六、记忆口诀

"位置在前,关键字在后"

  • / 左边:只能位置传
  • * 右边:只能关键字传
  • 两者之间:随便传

七、总结

概念 一句话总结
位置参数 按顺序传入
关键字参数 按名字传入
/ 它左边的是"专用座位",只能按顺序坐
* 它右边的是"指定座位",必须喊名字坐
相关推荐
赶紧写完去睡觉5 小时前
Anaconda 创建虚拟环境与使用
python·pycharm·conda
Herbert_hwt6 小时前
建立Java程序开发
java·开发语言
你驴我6 小时前
WhatsApp 多账号下消息已读回执的实时聚合与推送实践
后端·python
愚公移码6 小时前
蓝凌EKP18产品:流程虚拟机(PVM)
java·开发语言·前端
十月的皮皮6 小时前
stm20260720-从新手 C 到量产 STM32 工程:程序设计推导指南
c语言·开发语言·stm32·stm32cubemx·hal库
依然范特东7 小时前
动手学深度学习笔记--卷积层、微调
人工智能·笔记·深度学习
Echo缘7 小时前
嵌入式系统C语言资源分类与内存分布分析
c语言·开发语言
JaneConan8 小时前
鸿蒙 ArkUI 深水区:@Watch 和 @Observed,状态变了「自动跑」+ 嵌套对象「深层重绘」
开发语言·后端·ui·harmonyos
赤水无泪8 小时前
qt中图标、名称的设置方式
开发语言·qt