我是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

07-28 02:36
查看更多