星号*在Python中意味着什么?

Mar*_*n08 295 python

*在C中具有特殊含义,就像在C中一样吗?我在Python Cookbook中看到了这样的函数:

def get(self, *a, **kw)
Run Code Online (Sandbox Code Playgroud)

您能否向我解释或指出我能在哪里找到答案(Google将*解释为外卡字符,因此我找不到满意的答案).

非常感谢你.

S.L*_*ott 252

请参阅语言参考中的函数定义.

如果表单*identifier存在,则将其初始化为接收任何多余位置参数的元组,默认为空元组.如果表单**identifier存在,则将其初始化为接收任何多余关键字参数的新字典,默认为新的空字典.

另请参阅函数调用.

假设有人知道位置和关键字参数是什么,这里有一些例子:

例1:

# Excess keyword argument (python 2) example:
def foo(a, b, c, **args):
    print "a = %s" % (a,)
    print "b = %s" % (b,)
    print "c = %s" % (c,)
    print args

foo(a="testa", d="excess", c="testc", b="testb", k="another_excess")
Run Code Online (Sandbox Code Playgroud)

正如您在上面的示例中所看到的,我们a, b, cfoo函数的签名中只有参数.由于dk不存在,它们被放入args字典中.该计划的输出是:

a = testa
b = testb
c = testc
{'k': 'another_excess', 'd': 'excess'}
Run Code Online (Sandbox Code Playgroud)

例2:

# Excess positional argument (python 2) example:
def foo(a, b, c, *args):
    print "a = %s" % (a,)
    print "b = %s" % (b,)
    print "c = %s" % (c,)
    print args

foo("testa", "testb", "testc", "excess", "another_excess")
Run Code Online (Sandbox Code Playgroud)

在这里,既然我们正在测试位置参数,那么多余的参数必须在最后,并将*args它们打包成一个元组,所以这个程序的输出是:

a = testa
b = testb
c = testc
('excess', 'another_excess')
Run Code Online (Sandbox Code Playgroud)

您还可以将字典或元组解压缩为函数的参数:

def foo(a,b,c,**args):
    print "a=%s" % (a,)
    print "b=%s" % (b,)
    print "c=%s" % (c,)
    print "args=%s" % (args,)

argdict = dict(a="testa", b="testb", c="testc", excessarg="string")
foo(**argdict)
Run Code Online (Sandbox Code Playgroud)

打印:

a=testa
b=testb
c=testc
args={'excessarg': 'string'}
Run Code Online (Sandbox Code Playgroud)

def foo(a,b,c,*args):
    print "a=%s" % (a,)
    print "b=%s" % (b,)
    print "c=%s" % (c,)
    print "args=%s" % (args,)

argtuple = ("testa","testb","testc","excess")
foo(*argtuple)
Run Code Online (Sandbox Code Playgroud)

打印:

a=testa
b=testb
c=testc
args=('excess',)
Run Code Online (Sandbox Code Playgroud)

  • 虽然这是一个非常精确的定义,但这是一个非常糟糕的解释; 并且极不可能真正帮助陷入困境的程序员. (225认同)
  • 我觉得这个解释很有启发性.该评论者明确表示"假设有人知道位置和关键字的论点是什么." 所以他做得非常出色.所有标准都是很好的解释 (6认同)
  • 文档的链接已被破坏. (2认同)

Jas*_*ker 169

我只有一件事要补充,其他答案并不清楚(为了完整性).

调用函数时,您也可以使用星号.例如,假设你有这样的代码:

>>> def foo(*args):
...     print(args)
...
>>> l = [1,2,3,4,5]
Run Code Online (Sandbox Code Playgroud)

您可以将列表l传递给foo,就像这样......

>>> foo(*l)
(1, 2, 3, 4, 5)
Run Code Online (Sandbox Code Playgroud)

你也可以为词典做同样的事情......

>>> def foo(**argd):
...     print(argd)
...
>>> d = {'a' : 'b', 'c' : 'd'}
>>> foo(**d)
{'a': 'b', 'c': 'd'}
Run Code Online (Sandbox Code Playgroud)

  • 很抱歉在7年之后提出这个问题,但是如果你从fn声明中删除了`**`来只有`def foo(argd):`并且你运行`foo(d)`你会得到相同的结果.那为什么要用'**'? (10认同)
  • @David是的,你是对的.这个例子只是为了演示如何"解包"一个字典,然后在函数内"重新包装"它.例如,`foo(a ="b",c ="d")`也会提供与`foo(**d)`相同的输出. (4认同)
  • 为了清楚起见,此示例在将序列(例如列表)作为参数传递给使用“*args”作为任意数量的位置参数的函数时使用“*”来解包。 (3认同)
  • 我看到了第一个答案,然后我说:“不,这不是我想要的”,然后我看到了您的答案:) (2认同)

Sal*_*ley 72

所有上述答案都非常清晰和完整,但仅仅为了记录,我想确认python中*和**的含义与C中类似外观操作符的含义完全没有相似之处.

它们被称为argument-unpacking和keyword-argument-unpacking运算符.

  • 必要的澄清,我最初的想法是通过引用传递 * (2认同)

HUA*_*UAH 38

单个星形意味着变量'a'将是提供给函数的额外参数的元组.双星意味着变量'kw'将是随关键字提供的额外参数的可变大小字典.

尽管实际行为已被指出,但有时仍然非常不直观.编写一些示例函数并使用各种参数样式调用它们可以帮助您了解允许的内容和结果.

def f0(a)
def f1(*a)
def f2(**a)
def f3(*a, **b)
etc...
Run Code Online (Sandbox Code Playgroud)

  • 不要选择,但如果使用单个星形,则参数存储为元组,而不是列表. (10认同)

Cli*_*ler 27

我发现*在编写一个将另一个回调函数作为参数的函数时很有用:

def some_function(parm1, parm2, callback, *callback_args):
    a = 1
    b = 2
    ...
    callback(a, b, *callback_args)
    ...
Run Code Online (Sandbox Code Playgroud)

这样,调用者可以传递任意额外的参数,这些参数将被传递给他们的回调函数.好消息是回调函数可以使用正常的函数参数.也就是说,它根本不需要使用*语法.这是一个例子:

def my_callback_function(a, b, x, y, z):
    ...

x = 5
y = 6
z = 7

some_function('parm1', 'parm2', my_callback_function, x, y, z)
Run Code Online (Sandbox Code Playgroud)

当然,闭包提供了另一种做同样事情的方法,而不需要你通过some_function()和my_callback_function()传递x,y和z.