普通参数与关键字参数


289

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


6
您可能还想阅读PEP 3102,他们正在整理Python 3中的某些内容。请参阅:python.org/dev/peps/pep-3102
Ben Hoyt

而且是否有默认值与它无关(除非您是否需要为其传递值),对吗?
09年


@Ben Hoyt在下面的内容中添加了一个答案,涵盖了Python 3,必需的关键字参数
Christophe Roussy,2016年

Answers:


346

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

在调用方(这是其他评论者提到的),您可以通过名称指定一些函数自变量。您必须在所有不带名称的参数(位置参数)之后提及它们,并且对于所有根本没有提及的参数,都必须有默认值

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

def my_function(arg1, arg2, **kwargs)

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

def my_function(**kwargs):
    print str(kwargs)

my_function(a=12, b="abc")

{'a': 12, 'b': 'abc'}

5
+1并被接受:您是唯一谈论两种位置+关键字参数的人,其他所有人都以为我是在谈论第一个或第二个(但它们仍然是不错的帖子)。谢谢!
mk12

34
措辞不清楚:通常情况下,您在调用方谈论参数,而在被调用方谈论参数。
glglgl 2012年

3
参数名称必须为kwargs还是我可以将其重命名为sth。喜欢optionsdef my_fuction(arg1, arg2, **options))吗?
布鲁斯·孙

1
该名称可以是任何东西,虽然kwargs是约定时,有没有更合适的名称
马特·齐默曼

我认为这里解释的第二个概念在技术上称为任意关键字参数。
Anshul Dahiya

188

最后一种语言功能在区分上很重要。考虑以下功能:

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'}

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


3
很好的答案!请注意,在更改函数定义(例如)之前*positional和之后,可以传递必需的位置参数。这是位置和必填项。请注意,位置应答意味着位置参数的可选和可变数量。**keywordsdef foo(arg1, *positional, **keywords):arg1
shaffooo

2
是的,好的答案。另请注意:如果调用函数foo(bar=True),则可以使用bar = keywords.pop('bar')与相同的值bar = keywords.pop('bar', None)。对于默认值,请使用bar = keywords.pop('bar', False)
olibre

111

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

def foo(bar, baz):
    pass

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

3
谢谢你 我可以将关键字arg指定为位置arg,又可以将位置arg 指定为关键字arg,这非常有用。
卢克·戴维斯

47

位置参数

他们前面没有关键字。顺序很重要!

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)

8
恕我直言,第三个示例(默认参数)尚不清楚。我认为您正在谈论的是当一个或多个参数声明默认值并且调用使用位置表示法,但是提供的LESS少于声明的参数数量时会发生什么。但是,您的示例声明了3,在调用中有3,因此默认值根本无效!您是否打算省略第三个参数。例如func("bar", 5)?然后说hello得到它的默认值3
ToolmakerSteve

25

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

  1. 按位置。位置参数没有关键字,而是首先分配的。

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

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

如果不使用位置参数,那么-是的- 编写的所有内容实际上都是关键字参数。

调用一个函数您对使用位置或关键字或混合物的决定。您可以根据需要选择所有关键字。我们中有些人没有做出选择,而是使用位置参数。


1
哦,我当时在想参数,实际上是参数(传递的参数)。谢谢!
2009年

24

令我感到惊讶的是,似乎没有人指出可以像这样通过字典来传递形式参数的键参数参数。

>>> 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
>>> 

11
+1是一种有用的技术。没有,您的观点会更清楚, **kwargs。这将证明即使是具有固定参数数量的简单func def也可以提供字典。也就是说,它不需要定义中的任何内容。然后,您可以添加第二个示例,定义中带有** kwargs,并说明如何通过该示例使用字典中的EXTRA项目。
ToolmakerSteve

1
我已经在各种库的源代码中看到了这种情况,并且感到非常困惑。感谢您清理!
Craig Labenz 2014年

3
上面的第四个形式参数-如果使用包含“ a”,“ b”和“ c”以外的键的字典调用func,则必须使用** kwargs。
Eduardo

对我来说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))
阿克塞尔Bregnsbo

17

使用Python 3里,你可以有两个必需和非必需的关键字参数


可选:(为参数“ 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'`

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


3
要求的变体是相当有用的。它敦促在不提供默认值的情况下按名称给出args,这通常没有意义。
TNT

默认值看起来不错,可以帮助您节省启动时间,但从长远来看,默认值可以是PITA。
Christophe Roussy

11

令我惊讶的是,没有人提到您可以使用*argsand **kwargs从此站点)混合使用位置参数和关键字参数来进行类似的事情:

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

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


0

我正在寻找一个使用类型注释的默认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 {}

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.