如何解包嵌套迭代器传入可变参数函数并扁平化深层迭代器?
如何将嵌套的迭代器/可迭代对象解包后作为可变参数函数的参数传入?
问题场景1:类构造函数的迭代器传参问题
先看这段代码:
class k: def __init__(*args): self._args = args def mimethod(self, attrname:str): return type(self)(getattr(arg, attrname) for arg in self._args)
这里的getattr(arg, attrname) for arg in self._args是个生成器迭代器,直接传入type(self)(类k的构造函数)时,会被当成单个参数,导致self._args变成(生成器对象,),len(args)等于1,完全不符合预期。
解决方法
在迭代器前加*解包操作符,把迭代器里的每个元素逐个传入可变参数:
class k: def __init__(*args): self._args = args def mimethod(self, attrname:str): # 用*解包生成器,每个getattr结果都成为独立参数 return type(self)(*(getattr(arg, attrname) for arg in self._args))
这样__init__的*args就会接收生成器产出的所有元素,self._args的长度和原self._args一致,每个元素都是对应对象的attrname属性值。
问题场景2:可变参数函数的迭代器传参问题
再看这段代码:
import sys import io def variadic_function(*args, file_stream = sys.stdout): print("\n".join(str(arg) for arg in args), file=sys.stdout) strm = io.StringIO() names = ('LUciA', 'SoFiA', 'mArIA', 'MARTInA', 'pAuLa', 'LuCaS', 'hUgO', 'mArTiN', 'dAnIeL', 'pAbLo') # 原调用有语法错误+传参逻辑错误 variadic_function(name[0].upper()+ name[1:].lower() for name in names, file=strm) print(strm.getvalue())
原调用有两个问题:一是生成器后面多了逗号,导致语法错误;二是即使去掉逗号,生成器也会被当作单个参数传入,args里只有一个生成器对象,无法正确拼接输出名字。
解决方法
同样用*解包生成器,同时修正关键字参数的名字(函数定义的是file_stream):
import sys import io def variadic_function(*args, file_stream = sys.stdout): print("\n".join(str(arg) for arg in args), file=file_stream) # 修正file参数为传入的file_stream strm = io.StringIO() names = ('LUciA', 'SoFiA', 'mArIA', 'MARTInA', 'pAuLa', 'LuCaS', 'hUgO', 'mArTiN', 'dAnIeL', 'pAbLo') # 用*解包生成器,每个格式化后的名字都是独立参数 variadic_function(*(name[0].upper() + name[1:].lower() for name in names), file_stream=strm) print(strm.getvalue())
修改后,variadic_function的args会包含10个格式化后的名字(比如Lucia、Sofia等),"\n".join会把它们按行输出到strm中。
核心原理
Python中,当你把可迭代对象(生成器、列表、元组等)直接传给带*args的函数时,整个可迭代对象会被当作args的第一个元素。要让可迭代对象的每个元素都成为args的独立元素,必须在可迭代对象前加上*操作符,它会把可迭代对象“展开”,逐个传入参数。
内容的提问来源于stack exchange,提问作者Toothpick Anemone
相关产品推荐
相关产品推荐

