我需要通过巨大list/ tuple通过功能*args.
def f(*args): # defined in foreign module
pass
arguments = tuple(range(10000))
f(*arguments)
Run Code Online (Sandbox Code Playgroud)
我想知道函数调用会发生什么.
它是否处理arguments类似于任何位置变量:在执行期间保存并按需访问?或者arguments甚至在身体执行之前迭代,扩展位置参数?或者是别的什么?
pok*_*oke 13
使用发电机的简单测试:
def gen():
print('Yielding 1')
yield 1
print('Yielding 2')
yield 2
print('Yielding 3')
yield 3
arguments = gen()
def f(*args):
pass
f(*arguments)
# Yielding 1
# Yielding 2
# Yielding 3
Run Code Online (Sandbox Code Playgroud)
从输出中可以看出,传递*arguments实际上会解压缩整个迭代,因为从技术上讲,你告诉Python使用*arguments语法将iterable作为单独的参数传递.函数定义也使用*args哪个使Python将参数重新包装回元组并不重要.
所以是的,你打开包装清单只是为了再次打包.您可以直接传递列表来避免这种情况.
是的,*arguments调用语法必须迭代arguments迭代,原因有两个:
您传入的是列表,但*args函数中的variable-size参数是一个元组.所以元素必须在这里复制.
调用语法必须可用于任何函数,在这些函数中,您可能具有实际的位置参数,而不是*varargs变量或除变量之外.
例如,如果函数签名是def f(foo, *args):,则第一个元素必须单独传递.
原则上,CPython可以针对调用中使用的元组的所有值function(*tupleargs)最终在*varargs参数中进行优化,并重新使用该元组.然而,这实际上并不是那么常见,没有人这样做.
请注意,对于**kwargs调用语法,可变性的附加挑战使得共享对象的使用非常糟糕; 你必须创建一个使用的dict的副本,否则函数或调用者可能会改变该字典,其中的更改反映在另一个引用中.