【问题标题】:Normal arguments vs. keyword arguments普通参数与关键字参数
【发布时间】:2010-11-27 23:45:42
【问题描述】:

“关键字参数”与常规参数有何不同?不能将所有参数都作为name=value 传递而不是使用位置语法吗?

【问题讨论】:

  • 您可能还想阅读 PEP 3102——他们正在 Python 3 中整理其中的一些内容。请参阅:python.org/dev/peps/pep-3102
  • 和有没有默认值也没有关系(除了要不要给它传值),对吧?
  • @Ben Hoyt 在下面添加了一个答案,涵盖 Python 3,必需的关键字参数

标签: python arguments keyword optional-parameters named-parameters


【解决方案1】:

有两种方法可以将参数值分配给函数参数,两种方法都可以使用。

  1. 按位置。位置参数没有关键字,先赋值。

  2. 按关键字。关键字参数具有关键字,并在位置参数之后分配第二个。

请注意,可以选择使用位置参数。

如果 you 不使用位置参数,那么 - 是的 - you 写的所有内容都会变成关键字参数。

调用一个函数时,你决定使用位置或关键字或混合。如果需要,您可以选择执行所有关键字。我们中的一些人不会做出这种选择,而是使用位置参数。

【讨论】:

  • 哦,我在想参数,实际上它是参数(I 传递的内容)。谢谢!
【解决方案2】:

使用关键字参数与普通参数一样,只是顺序无关紧要。比如下面两个函数调用是一样的:

def foo(bar, baz):
    pass

foo(1, 2)
foo(baz=2, bar=1)

【讨论】:

  • 谢谢。我可以both将关键字arg指定为位置arg,将位置arg指定为关键字arg,这非常有用。
  • 注意:这对于仅位置参数是不可能的(在 Python 3.8 中接受的 PEP 570 中引入)。签名为pow(x, y, z=None, /)pow 具有仅位置参数(参数列表中的/ 表示所有前面的参数都是仅位置参数。通过此更改,pow(x=5, y=3) 导致Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: pow() takes no keyword arguments。参见python.org/dev/peps/pep-0570
【解决方案3】:

位置参数

它们之前没有关键字。顺序很重要!

func(1,2,3, "foo")

关键字参数

他们在前面有关键字。它们可以按任何顺序排列!

func(foo="bar", baz=5, hello=123)

func(baz=5, foo="bar", hello=123)

您还应该知道,如果您使用默认参数而忽略插入关键字,那么顺序将很重要!

def func(foo=1, baz=2, hello=3): ...
func("bar", 5, 123)

【讨论】:

  • 恕我直言,第三个示例(默认参数)不清楚。我认为您正在谈论当一个或多个参数声明默认值时会发生什么,并且调用使用位置表示法,但提供的参数少于声明的参数数量。但是,您的示例声明了 3 个,调用中声明了 3 个,因此默认值根本不起作用!您是否打算省略第三个参数。例如func("bar", 5)?然后说hello 的默认值是3
【解决方案4】:

我很惊讶没有人提到您可以使用*args**kwargs (from this site) 混合位置参数和关键字参数来做类似这样的鬼鬼祟祟的事情:

def test_var_kwargs(farg, **kwargs):
    print "formal arg:", farg
    for key in kwargs:
        print "another keyword arg: %s: %s" % (key, kwargs[key])

这允许您使用可能包含您不想预先定义的键的任意关键字参数。

【讨论】:

    【解决方案5】:

    最后一个语言特性的区别很重要。考虑以下函数:

    def foo(*positional, **keywords):
        print "Positional:", positional
        print "Keywords:", keywords
    

    *positional 参数将存储传递给foo() 的所有位置参数,您可以提供的数量没有限制。

    >>> foo('one', 'two', 'three')
    Positional: ('one', 'two', 'three')
    Keywords: {}
    

    **keywords 参数将存储任何关键字参数:

    >>> foo(a='one', b='two', c='three')
    Positional: ()
    Keywords: {'a': 'one', 'c': 'three', 'b': 'two'}
    

    当然,您可以同时使用两者:

    >>> foo('one','two',c='three',d='four')
    Positional: ('one', 'two')
    Keywords: {'c': 'three', 'd': 'four'}
    

    这些功能很少使用,但有时它们非常有用,知道哪些参数是位置参数或关键字很重要。

    【讨论】:

    • 优秀的答案!请注意,如果我们更改像def foo(arg1, *positional, **keywords): 这样的函数定义,则可以在*positional**keywords 之前传递所需的位置参数。这里arg1 是位置和必需的。请注意,答案中的位置表示可选和可变数量的位置参数。
    • 是的,很好的答案。另一个注意事项:如果你调用你的函数foo(bar=True),你可以使用bar = keywords.pop('bar')获取值,与bar = keywords.pop('bar', None)相同。默认值,使用bar = keywords.pop('bar', False)
    【解决方案6】:

    有两个相关的概念,都称为“关键字参数”。

    在调用方,正如其他评论者所提到的,您可以按名称指定一些函数参数。您必须在所有没有名称的参数之后提及它们(位置参数),并且对于任何根本没有提及的参数都必须有默认值

    另一个概念是在函数定义方面:您可以定义一个按名称获取参数的函数——您甚至不必指定这些名称是什么。这些是纯关键字参数,不能按位置传递。语法是

    def my_function(arg1, arg2, **kwargs)
    

    您传递给此函数的任何关键字参数都将被放入名为kwargs 的字典中。您可以在运行时检查此字典的键,如下所示:

    def my_function(**kwargs):
        print str(kwargs)
    
    my_function(a=12, b="abc")
    
    {'a': 12, 'b': 'abc'}
    

    【讨论】:

    • +1 并接受:你是唯一一个同时讨论位置+关键字参数的人,其他人要么认为我在谈论第一个或第二个(但他们仍然是好帖子)。谢谢!
    • 措辞不清楚:通常你说的是调用方的参数,而被调用方的参数。
    • 参数名称是不是必须是kwargs 或者我可以重命名它。喜欢options (def my_fuction(arg1, arg2, **options))?
    • 名称可以是任何名称,尽管kwargs 是没有更合适名称时的约定
    • 我认为这里解释的第二个概念在技术上称为任意关键字参数。
    【解决方案7】:

    令我惊讶的是,似乎没有人指出可以像这样传递满足形式参数的键控参数参数字典。

    >>> def func(a='a', b='b', c='c', **kwargs):
    ...    print 'a:%s, b:%s, c:%s' % (a, b, c)
    ... 
    >>> func()
    a:a, b:b, c:c
    >>> func(**{'a' : 'z', 'b':'q', 'c':'v'})
    a:z, b:q, c:v
    >>> 
    

    【讨论】:

    • +1 表示有用的技术。如果没有, **kwargs,您的观点会更清楚。这将证明即使是一个简单的 func def,具有固定的参数 #,也可以提供一个字典。也就是说,它不需要任何花哨的定义。然后您可以添加第二个示例,在定义中使用 **kwargs,并显示字典中的 EXTRA 项目如何通过它获得。
    • 我在各种库的源代码中看到了这种情况,很困惑。感谢您清理它!
    • 对我来说print 'a:%s, b:%s, c:%s' % (a, b, c) 给出了语法错误,但是print('a:%s, b:%s, c:%s' % (a, b, c)) 有效。 Python版本的东西?无论如何感谢你的洞察力,直到现在我使用的是更笨重的print('a:{}, b:{}, c:{}'.format(a, b, c))
    • 这表明默认参数可以在没有传入的情况下使用,也可以被覆盖/指定。但我认为第二个示例 func(**kwargs) 传入确实是多余的,因为可以简单地使用位置参数调用 >>> func('z', 'q', 'v')。此外,如果你曾经做过类似 >>> func('p', **{'a' : 'z', 'b':'q', 'c':'v'}) 的事情,你会得到一个参数“a”的多个值错误。
    【解决方案8】:

    使用 Python 3,您可以拥有 必需和非必需关键字 arguments


    可选:(为参数“b”定义的默认值)

    def func1(a, *, b=42):
        ...
    func1(value_for_a) # b is optional and will default to 42
    

    必需(未为参数“b”定义默认值):

    def func2(a, *, b):
        ... 
    func2(value_for_a, b=21) # b is set to 21 by the function call
    func2(value_for_a) # ERROR: missing 1 required keyword-only argument: 'b'`
    

    这在您有许多相似的参数彼此相邻的情况下会有所帮助,尤其是当它们属于同一类型时,在这种情况下,我更喜欢使用命名参数,或者如果参数属于一起,我会创建一个自定义类。

    【讨论】:

    • required 变体非常有用。它敦促按名称给出参数而不提供默认值,这通常没有意义。
    • 默认值看起来不错,可以帮助您在开始时节省时间,但从长远来看,默认值可以是 PITA。
    【解决方案9】:

    我正在寻找一个使用类型注释具有默认 kwargs 的示例:

    def test_var_kwarg(a: str, b: str='B', c: str='', **kwargs) -> str:
         return ' '.join([a, b, c, str(kwargs)])
    

    示例:

    >>> print(test_var_kwarg('A', c='okay'))
    A B okay {}
    >>> d = {'f': 'F', 'g': 'G'}
    >>> print(test_var_kwarg('a', c='c', b='b', **d))
    a b c {'f': 'F', 'g': 'G'}
    >>> print(test_var_kwarg('a', 'b', 'c'))
    a b c {}
    

    【讨论】:

      【解决方案10】:

      只是在调用函数时补充/添加一种方式来定义未在关键字中分配的参数的默认值

      def func(**keywargs):
      if 'my_word' not in keywargs:
          word = 'default_msg'
      else:
          word = keywargs['my_word']
      return word
      

      通过以下方式调用:

      print(func())
      print(func(my_word='love'))
      

      你会得到:

      default_msg
      love
      

      阅读更多关于 *args**kwargs 在 python 中的信息:https://www.digitalocean.com/community/tutorials/how-to-use-args-and-kwargs-in-python-3

      【讨论】:

        猜你喜欢
        • 2023-03-31
        • 2018-01-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多