如何用列表推导式(List Comprehension)从两个列表生成两个新列表?
解决列表推导式生成两个新列表的报错问题
嘿,这个问题我之前折腾过!你现在的写法之所以会抛出unpack non-iterable float object错误,核心原因是你搞反了解包的方向:
你写的代码Av,Bv=[(zeta*wn*dt,wd*dt) for i,(wn,wd) in zip(wnv,wdv)],生成的是一个包含元组的列表(比如[(a1,b1), (a2,b2), ...]),但直接把这个列表赋值给Av,Bv时,Python会尝试把整个列表拆成两个元素——如果列表长度不是2就会报错,就算长度刚好是2,也不是你想要的「把所有元组的第一个元素归为Av,第二个归为Bv」的效果。
正确的一行实现方式
你需要用zip(*...)来对元组列表进行转置解包,把每个元组的对应元素分别收集起来,代码如下:
# 如果允许Av、Bv是元组,直接用这个 Av, Bv = zip(*[(zeta * wn * dt, wd * dt) for wn, wd in zip(wnv, wdv)]) # 如果需要Av、Bv是列表,转成list即可 Av, Bv = list(zip(*[(zeta * wn * dt, wd * dt) for wn, wd in zip(wnv, wdv)]))
原理简单解释
zip(*...)在这里的作用是把列表里的每个元组「拆解」并重新组合:
- 它会把所有元组的第一个元素提取出来,组成一个迭代器(赋值给Av)
- 把所有元组的第二个元素提取出来,组成另一个迭代器(赋值给Bv)
更省内存的优化(可选)
如果你的列表很大,用生成器表达式代替列表推导式可以节省内存(不需要先创建完整的元组列表):
Av, Bv = zip(*((zeta * wn * dt, wd * dt) for wn, wd in zip(wnv, wdv)))
举个实际例子验证:假设zeta=0.5,dt=2,wnv=[1,2,3],wdv=[4,5,6],运行代码后:
- Av会是
(1, 2, 3)(或对应的列表) - Bv会是
(8, 10, 12)(或对应的列表),完全符合你的需求~
内容的提问来源于stack exchange,提问作者JXB
相关产品推荐
相关产品推荐

