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

问题描述 投票:547回答:5

[*运算符在Python中是什么意思,例如zip(*x)f(**k)之类的代码?

  1. 如何在解释器内部处理?
  2. 是否会影响性能?是快还是慢?
  3. 什么时候有用,什么时候没用?
  4. 应该在函数声明中还是在调用中使用?
python syntax parameter-passing iterable-unpacking argument-unpacking
5个回答
845
投票

单星*将序列/集合解压缩为位置参数,因此您可以执行此操作:

def sum(a, b):
    return a + b

values = (1, 2)

s = sum(*values)

这将打开元组的包装,使其实际执行为:

s = sum(1, 2)

双星**只是使用字典并因此命名了参数:

values = { 'a': 1, 'b': 2 }
s = sum(**values)

您也可以组合:

def sum(a, b, c, d):
    return a + b + c + d

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

将执行为:

s = sum(1, 2, c=10, d=15)

另请参见Python文档的4.7.4 - Unpacking Argument Lists部分。


另外,您可以定义函数以使用*x**y参数,这使函数可以接受声明中未明确命名的任意数量的位置和/或命名参数。

示例:

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

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

或带有**

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

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

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

再次,您可以组合:

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

40
投票

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


17
投票

我发现这在您要“存储”函数调用时特别有用。

例如,假设我对功能'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

除了手动执行类似add(test [0],test [1])之类的丑陋操作外,没有其他方法可以调用add。另外,如果变量数量可变,则包含所需的所有if语句的代码可能会变得很丑陋。

另一个有用的地方是定义Factory对象(为您创建对象的对象)。假设您有一些工厂类,该类使Car对象返回。您可以这样做,以便myFactory.make_car('red','bmw','335ix')创建Car('red','bmw','335ix'),然后将其返回。

def make_car(*args):
   return Car(*args)

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


16
投票

它称为扩展调用语法。从documentation

如果语法* expression出现在函数调用中,则表达式必须计算为序列。来自该序列的元素被视为它们是附加的位置参数;如果存在位置参数x1,...,xN,并且表达式的计算结果为序列y1,...,yM,则等效于使用M + N个位置参数x1,...,xN,y1,...的调用。 ..,yM。

和:

如果语法** expression出现在函数调用中,则表达式必须求值为一个映射,该映射的内容被视为其他关键字参数。如果关键字同时出现在表达式中并且作为显式关键字参数出现,则会引发TypeError异常。


14
投票

[在函数调用中,单星将列表变成单独的参数(例如,如果zip(*x),则zip(x1,x2,x3)x=[x1,x2,x3]相同]),双星将字典变成单独的关键字参数(例如,f(**k)是如果f(x=my_x, y=my_y)k = {'x':my_x, 'y':my_y}相同。

在函数定义中,反之亦然:单星将任意数量的参数转换为列表,而双引号将任意数量的关键字参数转换为字典。例如。 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})”。

© www.soinside.com 2019 - 2024. All rights reserved.