我的Python代码中有两个类树:
BaseComponent BaseSeries
/ | \ |
Resistor Capacitor Inductor ESeries
BaseSeries
类树实现首选数,例如E-series,并生成一对幂之间的值集(例如,对于指数在1到3之间的E3序列,[1.0, 2.2, 4.7, 10, 22, 47, 100, 220, 470]
)。你知道吗
默认情况下,ESeries
和BaseSeries
的任何其他实例创建float
对象序列。我想使用这些类来创建Resistor
、Capacitor
和Inductor
对象序列。理想情况下,单独的Resistor
、Capacitor
、Inductor
和ESeries
类将保持其自身的可用性(即,不依赖于由其他类实现的方法)。你知道吗
这听起来像是一个多重继承的工作,但我有点困惑如何在Python(3)中最好地实现它。理想情况下,我只想定义如下:
class ResistorESeries(Resistor, ESeries):
pass
class CapacitorESeries(Capacitor, ESeries):
pass
class InductorESeries(Inductor, ESeries):
pass
为了创建产生电阻器、电容器和电感器序列的类,但是我不知道如何最好地告诉BaseSeries
实例来创建类型为Resistor
、Capacitor
和Inductor
的对象。我能想到两种方法,但我不能决定哪一种是最好的,我有一种感觉,有一种更简单,更具Python的方法,我错过了:
具有BaseSeries
包含指向由构造函数、子类中的类变量(例如Resistor.ELEMENT_TYPE = Resistor
)或子类提供的抽象属性设置的元素类型(例如Resistor
)的属性或变量:
class BaseSeries(object):
...
def elements(self):
# loop over numbers in this series
for v in self.values():
yield self.element_type(v)
@property
@abc.abstractmethod
def element_type(self):
return NotImplemented
class ESeries(BaseSeries):
....
class BaseComponent(object):
...
@property
def element_type(self):
return self
class Resistor(BaseComponent):
...
class ResistorESeries(Resistor, ESeries):
# now BaseSeries' `element_type` property is provided by `BaseComponent`
pass
这意味着ESeries
不能单独用作具体的对象,因为它没有实现这个不理想的属性/变量。
在BaseSeries
中创建元素时使用self
,其中self
将引用所需元素,只要Resistor
位于方法解析顺序的前面:
class BaseSeries(object):
...
def elements(self):
# loop over numbers in this series
for v in self.values():
# self here would refer to `Resistor` in
# `ResistorESeries` instances
yield self(v)
class ESeries(BaseSeries):
....
class BaseComponent(object):
...
class Resistor(BaseComponent):
...
class ResistorESeries(Resistor, ESeries):
pass
这样做的缺点是,在ESeries
的实例中,没有用作mix-in,self
将引用自身,它不支持正确的__init__
签名。你知道吗
那么,有没有人知道如何以一种Pythonic的方式最好地做到这一点,并且能够最大限度地重用自己的类?你知道吗
您可能在这里混合了一些概念——特别是“实例”和“类”——您的示例调用确实很复杂。你知道吗
我无法从您的设计中理解为什么BaseComponent树上的类需要沿着BaseSeries树继承:组件类型不能只是BaseSeries类上的一个属性吗?你知道吗
这只是使用class属性的问题,在您第一次尝试时建议的代码中,使用一个平淡无奇的
if
语句。你知道吗如果你认为你需要多重继承,你可以按照你的想法使用一个属性,并在那里使用相同的“If”语句。但是如果这两个层次结构都是这样的,我不明白为什么要强制使用多重继承,仅仅因为语言允许。你知道吗
也许您更喜欢另一种方式:组件树上的工厂方法,它将把一个ESeries类作为输入,并从中提取值。。。你知道吗
不管怎么说,您并没有弄清楚类和实例的区别。您是否需要一种方法来生成
的几个子类 “电容器系列”,每个等级的值不同? 或者你只需要“电容器”的实例,每一个都有不同的价值产生的系列?你知道吗
当然,对于您声明的所有内容,可能都需要类的用例,包括一系列类的工厂,但是您在代码片段中使用
self
作为可调用项,这表明您对此的立场并不坚定。你知道吗在这种情况下,首先,您需要所有方法来正确使用
super
。即使它们不应该跨两个层次结构存在,使用super
也只会调用超类上的适当方法。但是对于像__init__
这样的方法,这只是需要的。你知道吗如果您使用
super
设计一个合适的__init__
方法,并且总是使用命名参数,那么您的第二个策略将开箱即用,只需修复实例化调用(对self(v)
以外的对象)。使用命名参数并将剩余的参数传递给super
将确保树中的每个类都使用这些参数所需的内容—当Python到达层次结构的根并调用object
的__init__
时,就没有剩余的参数了相关问题 更多 >
编程相关推荐