Python 2.7中map生成函数值列表乘浮点数报错的咨询
问题根因说明
- 触发报错的核心逻辑:Python原生列表、元组这类内置序列类型,只支持和整数做乘法运算,运算规则是把序列内的元素重复N次拼接成新序列;如果和浮点数相乘,Python无法识别操作逻辑,就会抛出
can't multiply sequence by non-int of type 'float'的报错。 - 代码里的APF、mod目前都是原生Python列表类型,直接和浮点数做乘法刚好触发了这个规则限制。
- 代码里还有几处隐藏的笔误,就算解决了列表乘法的问题,也会阻塞运行:
- 变量名拼写错误:
sgima = (2*math.pi/1530)*APF定义的变量名是sgima,下一行sig = sigma + delta引用的是不存在的sigma变量,会触发NameError - 常量输入错误:
kaa = (math.pi/l1530)*mod里的l1530是把数字1530错打为小写字母L开头的字符串,同样会触发NameError - Python2整数除法坑:apFunc里的
(x-(5/2))/5片段,在Python2环境下两个整数相除会做截断取整,5/2的结果是2而非2.5,会导致高斯包络的中心位置偏移,和设计逻辑不符
- 变量名拼写错误:
最优实现方案(适配已导入的NumPy库,效率最高)
NumPy数组天生支持逐元素和浮点数的乘法、加减法、幂运算、开方操作,不需要反复转原生列表,修改只需要几处调整:
- 去掉所有把np.arange生成结果转成原生list的操作,直接用NumPy数组承载定义域序列
- 把自定义函数里用math库的标量函数替换为NumPy对应的向量化函数,让函数可以直接接收整个数组输入,不需要用map逐点遍历
- 修正所有笔误,直接用数组的逐元素运算逻辑写后续公式
修改后的可运行代码:
import numpy as np import math import cmath delta = 2.0*math.pi*1.46*((1.0/1530)-(1.0/1550)) #定义主函数,把math库的标量方法替换为NumPy向量化方法 def apFunc(x): # 修正整数除法问题,5/2改为5.0/2 return np.exp(-4*np.log(2)*((x-(5.0/2))/5)**2)*(1+np.cos((2*np.pi/0.001)*x)) # 去掉list()包裹,直接用NumPy数组作为定义域 Domain = np.arange(0,5,0.001) APF = apFunc(Domain) #定义调制函数,同样替换为NumPy向量化方法 def modFunc(x): return (1+np.cos((2*np.pi/0.001)*x)) d = np.arange(0,5,0.001) mod = modFunc(d) #修正笔误,直接用数组和浮点数逐元素运算 sigma = (2*np.pi/1530)*APF sig = sigma + delta # 把l1530修正为1530 kaa = (np.pi/1530)*mod # NumPy数组直接支持逐元素平方、加和、开方 gamma = np.sqrt(sig**2 + kaa**2)
备选方案(保留原生列表结构的实现方式)
如果不想改动现有列表结构,要实现列表逐元素和浮点数相乘的效果,需要用列表推导式对每个元素单独做乘法,不能直接用*运算符:
- 原来直接写
sigma = (2*math.pi/1530)*APF会报错,改成逐元素遍历:
scale_sigma = 2*math.pi/1530 sigma = [scale_sigma * val for val in APF]
- 后续算sig、kaa、gamma的逐元素运算,也需要用列表推导式配合zip遍历实现:
sig = [val + delta for val in sigma] scale_kaa = math.pi/1530 kaa = [scale_kaa * val for val in mod] gamma = [math.sqrt(s**2 + k**2) for s, k in zip(sig, kaa)]
这种方式的运行效率比NumPy数组方案低很多,仅适合短序列的简单运算。
内容的提问来源于stack exchange,提问作者Vahid Talebi
相关产品推荐
相关产品推荐

