这是什么意思 * 运算符在python中是指 zip(*x) 或者 f(**k) ?口译员内部如何处理?它会影响性能吗?是快还是慢?什么时候有用,什么时候不有用?它应该在函数声明或调用中使用吗?
*
zip(*x)
f(**k)
lh80um4z1#
单星 * 将序列/集合解压为位置参数,以便执行以下操作:
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节-解包参数列表。此外,还可以定义要执行的函数 *x 以及 **y 参数,这允许函数接受声明中未明确命名的任意数量的位置参数和/或命名参数。例子:
*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
bq3bfh9z2#
一个小问题:这些不是运算符。运算符在表达式中用于从现有值创建新值(例如,1+2变为3)。这里的*和**是函数声明和调用语法的一部分。
ecfdbz9o3#
我发现这对于“存储”函数调用特别有用。例如,假设我对函数“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语句。另一个有用的地方是定义工厂对象(为您创建对象的对象)。假设您有一个类工厂,它制造car对象并返回它们。你可以这样做 myFactory.make_car('red', 'bmw', '335ix') 创建 Car('red', 'bmw', '335ix') ,然后返回。
add(test[0], test[1])
myFactory.make_car('red', 'bmw', '335ix')
Car('red', 'bmw', '335ix')
def make_car(*args): return Car(*args)
当您要调用超类的构造函数时,这也很有用。
jw5wzhpr4#
在函数调用中,单星将列表转换为单独的参数(例如。 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} )".
zip(x1,x2,x3)
x=[x1,x2,x3]
f(x=my_x, y=my_y)
k = {'x':my_x, 'y':my_y}
def foo(*x)
foo(1,2,3)
x
[1,2,3]
def bar(**k)
bar(x=42, y=23)
k
{'x': 42, 'y': 23}
ugmeyewa5#
它被称为扩展调用语法。根据文件:如果syntax*表达式出现在函数调用中,则表达式的计算结果必须是一个序列。此序列中的元素被视为附加位置参数;如果存在位置参数x1,…,xn,并且表达式的计算结果是序列y1,…,ym,则这相当于使用m+n位置参数x1,…,xn,y1,…,ym的调用。以及:如果语法**表达式出现在函数调用中,则表达式必须计算为Map,Map的内容将被视为其他关键字参数。如果关键字同时出现在表达式和显式关键字参数中,则会引发typeerror异常。
5条答案
按热度按时间lh80um4z1#
单星
*
将序列/集合解压为位置参数,以便执行以下操作:这将解压元组,使其实际执行为:
双星
**
仅使用字典和命名参数执行相同的操作:您还可以组合:
将执行为:
另请参阅python文档的第4.7.4节-解包参数列表。
此外,还可以定义要执行的函数
*x
以及**y
参数,这允许函数接受声明中未明确命名的任意数量的位置参数和/或命名参数。例子:
或与
**
:这允许您指定大量可选参数,而不必声明它们。
同样,您可以组合:
bq3bfh9z2#
一个小问题:这些不是运算符。运算符在表达式中用于从现有值创建新值(例如,1+2变为3)。这里的*和**是函数声明和调用语法的一部分。
ecfdbz9o3#
我发现这对于“存储”函数调用特别有用。
例如,假设我对函数“add”进行了一些单元测试:
除了手动执行以下操作之外,没有其他方法可以调用add
add(test[0], test[1])
,这是丑陋的。另外,如果变量的数量可变,那么代码可能会变得非常难看,因为您需要所有if语句。另一个有用的地方是定义工厂对象(为您创建对象的对象)。假设您有一个类工厂,它制造car对象并返回它们。你可以这样做
myFactory.make_car('red', 'bmw', '335ix')
创建Car('red', 'bmw', '335ix')
,然后返回。当您要调用超类的构造函数时,这也很有用。
jw5wzhpr4#
在函数调用中,单星将列表转换为单独的参数(例如。
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}
)".ugmeyewa5#
它被称为扩展调用语法。根据文件:
如果syntax*表达式出现在函数调用中,则表达式的计算结果必须是一个序列。此序列中的元素被视为附加位置参数;如果存在位置参数x1,…,xn,并且表达式的计算结果是序列y1,…,ym,则这相当于使用m+n位置参数x1,…,xn,y1,…,ym的调用。
以及:
如果语法**表达式出现在函数调用中,则表达式必须计算为Map,Map的内容将被视为其他关键字参数。如果关键字同时出现在表达式和显式关键字参数中,则会引发typeerror异常。