我是python的新手,正在尝试FFT的python实现。我已经遇到上述错误一段时间了。我该怎么办?
import numpy
import cmath
def twiddle(r,s):
x = (cmath.exp((2*cmath.pi*1j*s)/r))
return x
def fft(signal):
n = len(signal)
if n==1:
return signal
else:
Feven=fft([signal[k] for k in range(0,n,2)])
Fodd=fft([signal[k] for k in range(1,n,2)])
for l in range (n/2):
F1 = Feven[l] + twiddle(n, -l) * Fodd[l]
F2 = Feven[l] - twiddle(n, -l) * Fodd[l]
return F1+F2
当我为Feven和Fodd添加打印语句并输入以下内容时:
print (fft([4.5, 3.4, 4.7, 3.8, 6.7, 8.0, 4.6, 7.8]))
我得到:
Traceback (most recent call last):
File "FFT.py", line 41, in <module>
print (fft([4.5, 3.4, 4.7, 3.8, 6.7, 8.0, 4.6, 7.8]))
File "FFT.py", line 29, in fft
Feven=fft([signal[k] for k in range(0,n,2)])
File "FFT.py", line 34, in fft
F1 = Feven[l] + twiddler(n, -l) * Fodd[l]
TypeError: 'complex' object has no attribute '__getitem__'
最佳答案
修正错误
问题是你的线
return F1+F2
这实际上导致
fft
立即返回(复数为F1 + F2
),而实际上它应该返回一个列表。我想您的意思是这样的:def fft(signal):
n = len(signal)
if n==1:
return signal
else:
Feven=fft([signal[k] for k in range(0,n,2)])
Fodd=fft([signal[k] for k in range(1,n,2)])
F1 = [Feven[l] + twiddle(n, -l) * Fodd[l] for l in range (n/2)]
F2 = [Feven[l] - twiddle(n, -l) * Fodd[l] for l in range (n/2)]
return F1+F2
您的代码的其他注释
可以使用Python's slice notation代替
[signal[k] for k in range(0,n,2)]
来编写signal[0:n:2]
。同样,您可以编写[signal[k] for k in range(1,n,2)]
代替signal[1:n:2]
。实际上,由于
n
是列表signal
的长度,因此可以忽略它,因为这是切片的默认行为。因此,您可以实际编写:Feven = fft(signal[::2])
Fodd = fft(signal[1::2])
在
else:
子句中包含一些“ else”代码,在外部包含一些“ else”代码是没有意义的。全部放在一起。由于
Fodd
数总是乘以旋转因子,为什么不这样做而不是两次呢?也许像这样:def fft(signal):
n = len(signal)
if n == 1:
return signal
feven = fft(signal[::2])
fodd = [twiddle(n, -k) * o for k, o in enumerate(fft(signal[1::2]))]
f1 = [e + o for e, o in zip(feven, fodd)]
f2 = [e - o for e, o in zip(feven, fodd)]
return f1 + f2