代码之家  ›  专栏  ›  技术社区  ›  Alex

使用“*args”,关键字参数变为位置参数?

  •  1
  • Alex  · 技术社区  · 7 年前

    def myfunc(a=1, *args):
        print(a)
        # *args have some other functionality, for example passed to a class instance, or whatever
    

    myfunc *args a

    myfunc(3, a=4)
    

    myfunc(a=4, b=5, 3) 明显地我只能这么做

    myfunc(4, 3)
    

    现在看来

    这里的示例是一个函数,但它也适用于类。说一个子类 __init__(a=3, *args) 以及其他99个传递给super的必需参数。我不想在子类中重复99个参数的定义,而是想重复 变为位置性。

    这个类和子类示例是我在编码中真正的问题。我想要一个带有可选关键字参数的子类

    我不是第一个遇到这个问题的人,但我找不到任何答案。

    2 回复  |  直到 7 年前
        1
  •  2
  •   MSeifert    7 年前

    a 不仅仅是位置性的:

    >>> import inspect
    >>> def myfunc(a=1, *args):
    ...     print(a)
    >>> inspect.signature(myfunc).parameters['a'].kind
    <_ParameterKind.POSITIONAL_OR_KEYWORD: 1>
    

    事实上,它可以作为关键字参数传入:

    >>> myfunc(a=4)
    4
    

    *args ,这就是位置参数的工作方式:

    >>> def myfunc2(a, b):
    ...     print(a)
    >>> myfunc2(1, a=2)
    TypeError: myfunc2() got multiple values for argument 'a'
    

    所有参数都必须按名称传递。

    然而 这在一定程度上使情况复杂化,因为它只收集位置参数。这意味着如果它应该收集 任何东西

    但如果你想推出自己的特例,你可以只接受 *args, **kwargs 首先检查它是否作为关键字(命名)参数传递,如果不是,则作为第一个位置参数传递:

    >>> def myfunc3(*args, **kwargs):
    ...     if 'a' in kwargs:
    ...         a = kwargs.pop('a')
    ...     else:
    ...         a = args[0]
    ...         args = args[1:]
    ...     print(a, args, kwargs)
    >>> myfunc3(1, a=2)
    2 (1,) {}
    >>> myfunc3(2, 1)
    2 (1,) {}
    

        2
  •  2
  •   sfbahr    4 年前

    Python 3引入了纯关键字参数: https://www.python.org/dev/peps/pep-3102/

    def myfunc(*args, a=1):
        print(a)
    

    然后 myfunc(3, a=4) 会很好的。