星运营商是什么意思?

可能重复:
* args和** kwargs是什么意思?

*运算符在Python中的含义是什么,比如像zip(*x)f(**k)这样的代码?

  1. 翻译人员在内部如何处理?
  2. 它会影响性能吗? 是快还是慢?
  3. 什么时候有用,什么时候不是?
  4. 应该在函数声明还是在调用中使用?

单星*将序列/集合解开成位置参数,所以你可以这样做:

 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) 

另请参阅第4.7.4节 – Python文档的解包参数列表 。


此外,您可以定义函数以获取*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 

一个小点:这些不是运营商。 在expression式中使用运算符来从现有值创build新值(例如,1 + 2变为3)。这里的*和**是函数声明和调用语法的一部分。

它被称为扩展调用语法。 从文档 :

如果语法*expression式出现在函数调用中,则expression式必须计算为一个序列。 来自这个序列的元素被视为是额外的位置参数; 如果存在位置参数x1,…,xN,并且expression式计算为序列y1,…,yM,则这相当于具有M + N位置参数x1,…,xN,y1,…的调用。 ..,嗯。

和:

如果语法**expression式出现在函数调用中,则expression式必须求值为映射,其内容被视为附加关键字参数。 如果关键字出现在expression和explicit关键字参数中,则会引发TypeErrorexception。

我觉得这个特别有用,当你想“存储”一个函数调用。

例如,假设我有一些函数“add”的unit testing:

 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,这很丑陋。 而且,如果variables的数量是可变的,那么代码可能会变得很糟糕,所有你需要的if语句。

另一个有用的地方是定义Factory对象(为你创build对象的对象)。 假设你有一些类的工厂,使汽车对象和返回它们。 你可以让myFactory.make_car('red','bmw','335ix')创buildCar('red','bmw','335ix'),然后返回它。

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

当你想调用一个超类的构造函数时,这也很有用。

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

在一个函数定义中,反过来也是这样:单星将任意数量的参数变成列表,而双重开始将任意数量的关键字variables转换成字典。 例如, 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} )“。