我尝试使用类继承来绘制具有不同频率 (
f
) 和幅度 (a
) 的正弦波。但在我看来它运行效率并不高。
这是我的代码,我将公共属性 f 和 a 放在父类中,将变量 t 放在子类中。
import math
from matplotlib import pyplot as plt
class Parent:
def __init__(self, f, a):
self.freq = f
self.ampl = a
self.color = (f/a/3, (f/a)/2, (f/a)) # some random RGB numbers
class Child(Parent):
def __init__(self, t, f, a):
super(Child, self).__init__(f, a)
self.time = t
def volt(self):
omega = 2*math.pi*self.freq
return self.ampl * math.sin(omega*self.time)
if __name__ == '__main__':
for (f,a) in [(0.05,1.5), (0.1,1)]:
color = Parent(f, a).color
time = [i for i in range(50)]
cl = [Child(x, f, a).volt() for x in time]
plt.plot(time, cl, color=color)
plt.xlabel("time")
plt.ylabel("amplitude")
plt.title(f"Voltage waveform for different frequencies")
plt.show()
它有效。但对于
Child(x, f, a)
的每个实例化,它也会运行 super().__init__
,这不会因每个变量 x
而改变。我想知道是否有一种方法可以在变量 Parent
的外循环中运行 f, a
并在变量 Child
的内循环中运行 x
。
我认为没有充分的理由在这里使用像
Parent
和 Child
这样的类。这些类上的大多数属性都是设置但不读取的,并且不需要多次读取任何属性。重新考虑您是否真的需要这些课程。
我建议的代码是--
import math
from matplotlib import pyplot as plt
def make_color(freq, ampl):
return (freq / ampl / 3, freq / ampl / 2, freq / ampl) # some random RGB numbers
def calc_volt(time, freq, ampl):
omega = 2 * math.pi * freq
return ampl * math.sin(omega * time)
if __name__ == "__main__":
for freq, ampl in [(0.05, 1.5), (0.1, 1)]:
color = make_color(freq, ampl)
time = [i for i in range(50)]
cl = [calc_volt(x, freq, ampl) for x in time]
plt.plot(time, cl, color=color)
plt.xlabel("time")
plt.ylabel("amplitude")
plt.title("Voltage waveform for different frequencies")
plt.show()
我同意对于像这样的简单问题,你不需要上课。但我用它作为例子来探索不同的设计。
没关系。我们继续上课吧。
Parent.__init__
中最重的部分是color
的计算,并且color
从不用于Child
的实例,因此计算被浪费了。我建议通过functools.cached_property
让它变得懒惰。
相关部分可以改为---
from functools import cached_property
class Parent:
def __init__(self, f, a):
self.freq = f
self.ampl = a
@cached_property
def color(self):
return (f / a / 3, (f / a) / 2, (f / a)) # some random RGB numbers
其实,有了类变量,我们就可以消除类继承部分:
import math
from matplotlib import pyplot as plt
class Parent:
freq = None
ampl = None
color = None
def __init__(self, f, a):
Parent.freq = f
Parent.ampl = a
Parent.color = (f/a/3, (f/a)/2, (f/a))
class Child:
def __init__(self, t):
self.time = t
def volt(self):
omega = 2*math.pi*Parent.freq
return Parent.ampl * math.sin(omega*self.time)
if __name__ == '__main__':
for (f,a) in [(0.05,1.5), (0.1,1)]:
Parent(f, a)
time = [i for i in range(50)]
cl = [Child(x).volt() for x in time]
plt.plot(time, cl, color=Parent.color)
plt.xlabel("time")
plt.ylabel("amplitude")
plt.title(f"Voltage waveform for different frequencies")
plt.show()
您可以为父类使用静态/类变量
import math
from matplotlib import pyplot as plt
class Parent:
freq = None
ampl = None
def __init__(self):
self.color = (self.freq/self.ampl/3, (self.freq/self.ampl)/2, (self.freq/self.ampl)) # some random RGB numbers
class Child(Parent):
def __init__(self, t):
self.time = t
def volt(self):
omega = 2 * math.pi * self.freq
return self.ampl * math.sin(omega * self.time)
if __name__ == '__main__':
for freq, ampl in [(0.05, 1.5), (0.1, 1)]:
Parent.freq = freq
Parent.ampl = ampl
color = Parent().color
time = [i for i in range(50)]
cl = [Child(x).volt() for x in time]
plt.plot(time, cl, color=color)
plt.xlabel("time")
plt.ylabel("amplitude")
plt.title("Voltage waveform for different frequencies")
plt.show()