我们可以让父类初始化的频率低于子类吗?
我尝试用类的继承来绘制不同频率(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
。
3 个回答
0
其实,使用类变量的话,我们可以省去类继承的部分:
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()
1
我觉得这里用到 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
,而且在 Child
的实例中从来没有用到这个 color
,所以这个计算是浪费的。我建议可以用 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
-1
你可以在父类中使用静态变量或类变量。
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()