# -*- coding: utf-8 -*-
import numpy as np
class HarmObj(object):
# Creates an instance for each harmonic.
def __init__(self, file_size):
self.mag = np.zeros((file_size))
self.phi = np.zeros((file_size))
self.freq = np.zeros((file_size))
class SignalObj(object):
# Creates an instance for the synthesized speech signal, which is formed by the
# harmonics.
def __init__(self, n_harm, file_size):
self.n_harm = n_harm
self.size = file_size
self.harmonics = [HarmObj(self.size) for i in xrange(self.n_harm)]
def update_values(self, a, freq, frame):
for harmonic in xrange(self.n_harm):
self.harmonics[harmonic].mag[frame] = np.abs(a[harmonic])
self.harmonics[harmonic].phi[frame] = np.angle(a[harmonic])
self.harmonics[harmonic].freq[frame] = freq[harmonic]
n_harm = 25
file_size = 100
signal = SignalObj(n_harm, file_size)
for frame in xrange(file_size):
#Nevermind this part, is just a simplification ;)
#----------------------------------------------
real_part = np.random.normal(0.0, 0.9, n_harm)
imag_part = np.random.normal(0.0, 0.9, n_harm)
a = real_part + 1j*imag_part
freq = np.random.normal(500.0, 200.0, n_harm)
#-----------------------------------------------
signal.update_values(a, freq, frame)
此脚本运行没有问题。然而,由于在语音信号中谐波和帧的数量可能很大,由于for
方法内的SignalObj.update_values
循环,代码在某种程度上会在计算上造成负担。
我相信一个" numpy-array"解决方案如
def update_values(self, a, freq, frame):
self.harmonics[:].mag[frame] = np.abs(a[:])
self.harmonics[:].phi[frame] = np.angle(a[:])
self.harmonics[:].freq[frame] = freq[:]
会更快。但上面的代码并不适用于对象列表。 所以,我想知道是否有办法改变列表属性或创建我自己的结构,然后允许上述优化的值设置过程。
PS。 :顺便提一下,避免此问题的一种可能解决方案是放弃HarmObj
类并将mag
,phi
和freq
属性直接关联到SignalObj
},即
class SignalObj(object):
def __init__(self, n_harm, file_size):
self.n_harm = n_harm
self.size = file_size
self.mag = np.zeros((n_harm, file_size))
self.phi = np.zeros((n_harm, file_size))
self.freq = np.zeros((n_harm, file_size))
def update_values(self, a, freq, frame):
self.mag[:, frame] = np.abs(a[:])
self.phi[:, frame] = np.angle(a[:])
self.freq[:, frame] = freq[:]
我在MATLAB版本中采用了这种解决方法,确实更快。但是,由于Python更有资源,我想知道是否有更优雅和pythonic的方式来完成这项工作;)。此外,保持HarmObj
实例分开将在以后开始操作时帮助我。
答案 0 :(得分:0)
由于您用于创建self.harmonics
这里简单说明了为什么会出现问题
class Foo()
__init__(self, foo):
self.foo = foo
foo = Foo('foo')
bar = [foo] * 3
for i in bar:
print i.foo
这会返回。
foo
foo
foo
看起来很好......除了它没有,因为它们都指向同一个foo
对象。所以
bar[0].foo = 'bar'
for i in bar:
print i.foo
返回:
bar
bar
bar
改为使用列表理解。
bar = [Foo('foo') for i in range(3)]
for i in bar:
print i.foo
bar[0].foo = 'bar'
for i in bar:
print i.foo
这给出了所需的
foo
foo
foo
bar
foo
foo
对列表进行快速操作,您也可以列出理解。
def update_harmonic(harmonic):
real_part = np.random.normal(0.0, 0.9, n_harm)
imag_part = np.random.normal(0.0, 0.9, n_harm)
a = real_part + 1j*imag_part
freq = np.random.normal(500.0, 200.0, n_harm)
signal.update_values(a, freq, frame)
self.harmonics = [x.update_harmonic() for x in self.harmonics]