天天看点

在函数调用中,星号运算符是什么意思? [重复]

本文翻译自:What does the star operator mean, in a function call? [duplicate]

This question already has an answer here:

这个问题已经在这里有了答案:
  • What does ** (double star/asterisk) and * (star/asterisk) do for parameters? **(双星号/星号)和*(星号/星号)对参数有什么作用? 19 answers 19个答案
  • asterisk in function call 3 answers 函数调用中的星号 3个答案

What does the

*

operator mean in Python, such as in code like

zip(*x)

or

f(**k)

?

*

运算符在Python中的含义是什么,例如

zip(*x)

f(**k)

  1. How is it handled internally in the interpreter? 在解释器内部如何处理?
  2. Does it affect performance at all? 它会影响性能吗? Is it fast or slow? 是快还是慢?
  3. When is it useful and when is it not? 什么时候有用,什么时候没有?
  4. Should it be used in a function declaration or in a call? 应该在函数声明中还是在调用中使用它?

#1楼

参考:https://stackoom.com/question/CG6Z/在函数调用中-星号运算符是什么意思-重复

#2楼

In a function call the single star turns a list into seperate arguments (eg

zip(*x)

is the same as

zip(x1,x2,x3)

if

x=[x1,x2,x3]

) and the double star turns a dictionary into seperate keyword arguments (eg

f(**k)

is the same as

f(x=my_x, y=my_y)

if

k = {'x':my_x, 'y':my_y}

.

在函数调用中,单星将列表变成单独的参数(例如

zip(x1,x2,x3)

如果

x=[x1,x2,x3]

zip(*x)

zip(x1,x2,x3)

相同),而双星则将其变成字典如果

k = {'x':my_x, 'y':my_y}

进入单独的关键字参数(例如

f(**k)

f(x=my_x, y=my_y)

k = {'x':my_x, 'y':my_y}

In a function definition it's the other way around: the single star turns an arbitrary number of arguments into a list, and the double start turns an arbitrary number of keyword arguments into a dictionary.

在函数定义中,反之亦然:单星将任意数量的参数转换为列表,而双引号将任意数量的关键字参数转换为字典。

Eg

def foo(*x)

means "foo takes an arbitrary number of arguments and they will be accessible through the list x (ie if the user calls

foo(1,2,3)

,

x

will be

[1,2,3]

)" and

def bar(**k)

means "bar takes an arbitrary number of keyword arguments and they will be accessible through the dictionary k (ie if the user calls

bar(x=42, y=23)

,

k

will be

{'x': 42, 'y': 23}

)".

例如

def foo(*x)

表示“ foo接受任意数量的参数,并且可以通过列表x进行访问(即,如果用户调用

foo(1,2,3)

,则

x

[1,2,3]

”和

def bar(**k)

表示“ bar接受任意数量的关键字参数,并且可以通过字典k访问它们(即,如果用户调用

bar(x=42, y=23)

,则

k

{'x': 42, 'y': 23}

)“。

#3楼

It is called the extended call syntax.

它称为扩展调用语法。

From the documentation :

从文档中 :
If the syntax *expression appears in the function call, expression must evaluate to a sequence. 如果语法* expression出现在函数调用中,则表达式必须计算为序列。 Elements from this sequence are treated as if they were additional positional arguments; 来自该序列的元素被视为它们是附加的位置参数; if there are positional arguments x1,..., xN, and expression evaluates to a sequence y1, ..., yM, this is equivalent to a call with M+N positional arguments x1, ..., xN, y1, ..., yM. 如果存在位置参数x1,...,xN,并且表达式的计算结果为序列y1,...,yM,则等效于使用M + N个位置参数x1,...,xN,y1,...的调用。 ..,yM。

and:

和:
If the syntax **expression appears in the function call, expression must evaluate to a mapping, the contents of which are treated as additional keyword arguments. 如果语法** expression出现在函数调用中,则表达式必须计算为一个映射,该映射的内容被视为其他关键字参数。 In the case of a keyword appearing in both expression and as an explicit keyword argument, a TypeError exception is raised. 如果关键字同时出现在表达式中并作为显式关键字参数出现,则会引发TypeError异常。

#4楼

The single star

*

unpacks the sequence/collection into positional arguments, so you can do this:

单颗星

*

将序列/集合解压缩为位置参数,因此您可以执行以下操作:
def sum(a, b):
    return a + b

values = (1, 2)

s = sum(*values)
           

This will unpack the tuple so that it actually executes as:

这将打开元组的包装,使其实际执行为:
s = sum(1, 2)
           

The double star

**

does the same, only using a dictionary and thus named arguments:

双星

**

功能相同,仅使用字典并因此命名参数:
values = { 'a': 1, 'b': 2 }
s = sum(**values)
           

You can also combine:

您还可以结合:
def sum(a, b, c, d):
    return a + b + c + d

values1 = (1, 2)
values2 = { 'c': 10, 'd': 15 }
s = sum(*values1, **values2)
           

will execute as:

将执行为:
s = sum(1, 2, c=10, d=15)
           

Also see section 4.7.4 - Unpacking Argument Lists of the Python documentation.

另请参阅Python文档的4.7.4-解压缩参数列表 。

Additionally you can define functions to take

*x

and

**y

arguments, this allows a function to accept any number of positional and/or named arguments that aren't specifically named in the declaration.

另外,您可以定义带有

*x

**y

参数的函数,这使函数可以接受在声明中未专门命名的任何数量的位置和/或命名参数。

Example:

例:
def sum(*values):
    s = 0
    for v in values:
        s = s + v
    return s

s = sum(1, 2, 3, 4, 5)
           

or with

**

:

或带有

**

def get_a(**values):
    return values['a']

s = get_a(a=1, b=2)      # returns 1
           

this can allow you to specify a large number of optional parameters without having to declare them.

这可以使您无需声明它们即可指定大量可选参数。

And again, you can combine:

再一次,您可以结合:
def sum(*values, **options):
    s = 0
    for i in values:
        s = s + i
    if "neg" in options:
        if options["neg"]:
            s = -s
    return s

s = sum(1, 2, 3, 4, 5)            # returns 15
s = sum(1, 2, 3, 4, 5, neg=True)  # returns -15
s = sum(1, 2, 3, 4, 5, neg=False) # returns 15
           

#5楼

One small point: these are not operators.

一点:这些不是运算符。

Operators are used in expressions to create new values from existing values (1+2 becomes 3, for example. The * and ** here are part of the syntax of function declarations and calls.

表达式中使用运算符从现有值创建新值(例如1 + 2变为3。这里的*和**是函数声明和调用语法的一部分。

#6楼

I find this particularly useful for when you want to 'store' a function call.

对于要“存储”函数调用的情况,我发现这特别有用。

For example, suppose I have some unit tests for a function 'add':

例如,假设我对功能“ add”进行了一些单元测试:
def add(a, b): return a + b
tests = { (1,4):5, (0, 0):0, (-1, 3):3 }
for test, result in tests.items():
   print 'test: adding', test, '==', result, '---', add(*test) == result
           

There is no other way to call add, other than manually doing something like add(test[0], test[1]), which is ugly.

除了手动执行类似add(test [0],test [1])之类的丑陋操作外,没有其他方法可以调用add。

Also, if there are a variable number of variables, the code could get pretty ugly with all the if-statements you would need.

另外,如果变量数量可变,则所有需要的if语句的代码都会变得很丑陋。

Another place this is useful is for defining Factory objects (objects that create objects for you).

另一个有用的地方是定义Factory对象(为您创建对象的对象)。

Suppose you have some class Factory, that makes Car objects and returns them.

假设您有一些工厂类,该类使Car对象返回。

You could make it so that myFactory.make_car('red', 'bmw', '335ix') creates Car('red', 'bmw', '335ix'), then returns it.

您可以使myFactory.make_car('red','bmw','335ix')创建Car('red','bmw','335ix'),然后返回它。
def make_car(*args):
   return Car(*args)
           

This is also useful when you want to call a superclass' constructor.

当您要调用超类的构造函数时,这也很有用。