【问题标题】:Python optional, positional and keyword argumentsPython 可选、位置和关键字参数
【发布时间】:2012-11-21 03:25:27
【问题描述】:

这是我的一门课:

class metadict(dict):
    def __init__(self, do_something=False, *args, **kwargs)
        if do_something:
            pass
        super(metadict,self).__init__(*args,**kwargs)

这个想法是封装一个字典并使用特殊关键字添加一些功能。字典仍然可以保存do_something,尽管您不能在创建时添加它。对于所有其他方面,它的行为就像普通字典一样。

无论如何,问题是我给args 的任何东西都是从将第一个值分配给do_something 开始的,这不是我想要的。

我现在要做的是:

class metadict(dict):
    def __init__(self, do_something=False, *args, **kwargs)
        if not isinstance(do_something, bool):
            args = list(args)
            args.append(do_something)
        elif do_something:
            pass
        super(metadict,self).__init__(*args,**kwargs)

但我觉得不合适。我还可以检查 kwargs 中的 do_something 值,但情况会更糟,因为我弄乱了删除有用信息的签名...

python 中有什么方法可以安全地使用可选参数、位置参数和关键字参数吗? 如果没有,还有其他更简单的解决方法吗?

我在 python 2.6 上

【问题讨论】:

  • 我认为问题在于您在位置参数之前定义了关键字参数(do_something 是关键字,*args 是位置参数)。然后,当您将值作为构造函数中的第一个元素传递时,它会被传递给do_something。尝试将do_something 放在*args 之后。
  • @RocketDonkey 我试过但显然在 python 2.6 中不支持
  • 啊,有趣。无论如何,看起来你已经解决了,祝你一切顺利!
  • @RocketDonkey 我没有,但如果 3.0 版中有此功能,则意味着没有简单的解决方法。所以我只是运气不好。
  • 所以这很混乱,可能会导致其他问题并且绝对不值得回答(足够的免责声明?:)),但对我有用的一件事*不是打开包装*args(所以使用@987654333 @ 反而)。然后你可以把你的do_something=False 放在args 之后,做你的签名self, args, do_something=False, **kwargs。然后当你调用super 时,使用.__init__(args, **kwargs)。 *如果您使用 dict(one=1, two=2) 语法,这将不起作用,因为它依赖于传递一个迭代,然后由 dict 类本身解包。再次,可怕的解决方案,但如果你绝望...... :)

标签: python optional-arguments keyword-argument


【解决方案1】:

它是new in Python 3。 Python 2 中最好的解决方法是

def foo(*args, **kwargs):
    do_something = kwargs.pop("do_something", False)

您看到的行为发生是因为 Python 试图巧妙地匹配参数,因此例如,如果您传递太多位置参数,它将使关键字参数成为位置参数。

PS 为什么不将其存储为metadict 的属性而不是字典中的条目?

【讨论】:

  • 如果 OP 担心签名,解决方案很简单...记录功能。一个很好的文档,包含允许的参数、默认值等,如果通常比长签名更好。
  • 属性影响创建,根本不存储。基本上它告诉如果存在,字典将使用一种特殊的结构来创建,用于向字典提供元数据信息,如果不存在,则(几乎)完全透明。 @EnricoGiampieri 文档很棒,我会这样做,但是您会错过语义。所以inspect 不能正常工作,像sphinx 这样的文档工具也不能正常工作。归根结底,这只是一个设计决定。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-12-12
  • 2011-08-21
  • 2020-09-01
  • 2023-03-31
  • 2017-05-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多