You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python:__init__()出现'multiple values for bar'错误的原因及疑问

为什么会出现"multiple values for keyword argument"错误?

这个问题其实是Python参数解析规则在起作用,咱们把代码拆解开来一步步看就明白了:

首先看你的类定义:

class Foo(object):
    """Baffling"""
    def __init__(self, bar=None, *args):
        pass

这里的bar=None是一个带默认值的位置参数(注意,它不是仅限关键字参数),而*args的作用是收集所有未被匹配的位置参数。

接下来看触发错误的调用:foo = Foo(1, bar=2)
Python解析参数的顺序是这样的:

  1. 先匹配位置参数:第一个传入的1会被直接绑定到第一个位置参数bar上(self是实例自动传入的,不用手动传递);
  2. 然后处理关键字参数:你又传了bar=2,这时候Python发现bar已经被位置参数赋值过了,自然就会抛出TypeError: __init__() got multiple values for keyword argument 'bar'——相当于你给同一个参数传了两次值,一次用位置、一次用关键字,这肯定会冲突!

那为什么Foo(1)能正常运行?因为这个调用里,1被赋值给bar,*args收集到的是空元组,完全符合参数规则,所以没问题。

那这种写法为什么行不通?

核心原因是:在Python中,如果带默认值的参数定义在*args前面,它本质还是位置参数,只是当你没传位置值时会启用默认值。这就意味着,它既可以通过位置传递,也可以通过关键字传递,但不能同时用两种方式传——否则就会出现重复赋值的冲突。

怎么实现你想要的效果?

如果你想同时支持可变数量的位置参数,和带默认值的命名参数,有两种更合理的写法:

1. 使用仅限关键字参数(Python 3+ 推荐)

把*args放在前面,后面的参数就会变成仅限关键字参数,只能通过关键字传递:

class Foo(object):
    def __init__(self, *args, bar=None):
        pass

这样调用就不会有冲突了:

  • Foo(1) → args=(1,),bar=None
  • Foo(1, 2, bar=3) → args=(1,2),bar=3
  • Foo(bar='baz') → args=(),bar='baz'

2. 使用**kwargs(你提到的方法)

手动处理关键字参数,灵活性更高:

class Foo(object):
    def __init__(self, *args, **kwargs):
        bar = kwargs.pop('bar', None)
        # 这里可以处理args和剩下的kwargs
        pass

这种写法适合需要处理更多自定义关键字参数的场景。

内容的提问来源于stack exchange,提问作者Joshua Clayton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:19:45