*
运算符在Python中的含义是什么,例如zip(*x)
或f(**k)
等代码?
答案 0 :(得分:800)
单星*
将序列/集合解包为位置参数,因此您可以这样做:
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
答案 1 :(得分:40)
一点:这些不是运营商。运算符在表达式中用于从现有值创建新值(例如,1 + 2变为3。*和**这里是函数声明和调用语法的一部分。
答案 2 :(得分: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,除了手动执行add(test [0],test [1])之类的操作,这很丑陋。此外,如果存在可变数量的变量,那么代码可能会变得非常丑陋,并且需要使用所有if语句。
另一个有用的地方是定义Factory对象(为您创建对象的对象)。 假设你有一些类Factory,它会生成Car对象并返回它们。 你可以这样做,myFactory.make_car('red','bmw','335ix')创建Car('red','bmw','335ix'),然后返回它。
def make_car(*args):
return Car(*args)
当你想调用超类的构造函数时,这也很有用。
答案 3 :(得分:15)
它被称为扩展调用语法。来自documentation:
如果语法*表达式出现在函数调用中,则表达式必须求值为序列。来自这个序列的元素被视为它们是额外的位置参数;如果存在位置参数x1,...,xN,并且表达式求值为序列y1,...,yM,则这相当于具有M + N个位置参数x1,...,xN,y1,...的调用。 ..,yM。
和
如果语法**表达式出现在函数调用中,则表达式必须求值为映射,其内容被视为附加关键字参数。如果关键字出现在表达式和显式关键字参数中,则会引发TypeError异常。
答案 4 :(得分:11)
在函数调用中,单个星形将列表转换为单独的参数(例如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}
相同。
在函数定义中,它是另一种方式:单个星形将任意数量的参数转换为列表,并且double start将任意数量的关键字参数转换为字典。例如。 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}
)”