让Instrument
成为一个包含三个函数piano(self)
,guitar(self)
和trumpet(self)
的类。该类还有一个play(self)
函数,根据该类中表示的工具,它将调用正确的方法。
有没有办法只用一个类Instrument
(即没有其他抽象类)来定义调用play
方法时应该调用的方法?
换句话说,有没有办法做到以下几点:
my_piano = Instrument(piano)
my_piano.play() # calls piano(self) method
my_guitar = Instrument(guitar)
my_guitar.play() # calls guitar(self) method
my_trumpet = Instrument(trumpet)
my_trumpet.play() # calls trumpet(self) method
一个相当简单的方法,但不是很干净,是在构造函数中放置一个变量,然后在play
方法中放入很多条件,如下所示:
def Instrument(object):
def __init__(self, instrument_type):
self.instrument_type = instrument_type
def play(self):
if instrument_type == 0:
self.piano()
elif instrument_type == 1:
self.guitar()
elif instrument_type == 2:
self.trumpet()
这样做的正确方法是拥有一个Instrument
课程,然后是三个继承自Piano
的{{1}},Guitar
和Trumpet
课程。但是,根据我的需要,这将使事情变得复杂。
修改
根据要求,我解释了我的实际问题,几乎完全相同。
我有一个类Instrument
,它可以使用五种不同的方法来计算某些东西。它可以ComputeSth
,a(self)
,...,b(self)
的方式对其进行计算。
例如,有时我想根据f(self)
计算,有些时候根据a
进行计算。如果我这样做,这很容易:
c
但后来我注意到为了在我的代码的其他部分轻松使用这个类,我更愿意做my_computer = ComputeSth()
my_computer.a()
my_computer.c()
。所以,我认为在调用my_computer.compute()
时使用实际方法构造实例会很方便。我不想写其他五个类,因为它们实际上不代表五个不同的对象,而是五种不同的方法。我无法将函数compute(self)
,...,a
作为构造函数的输入传递,因为需要f
。
换句话说,与self
的示例相同,但“真实世界继承”更少。
答案 0 :(得分:6)
这是多态性的用途
class Instrument:
def play(self):
pass
class Guitar(Instrument):
def play(self):
print 'brau dau'
class Drum(Instrument):
def play(self):
print 'dum dum'
guitar = Guitar()
guitar.play()
drum = Drum()
drum.play()
答案 1 :(得分:3)
这肯定是错误的设计,但绝对可行:
class Instrument:
def __init__(self, method):
self.method = method
def play(self):
self.method(self)
def piano(self):
print("I am a piano")
def trumpet(self):
print("I am a trumpet")
def guitar(self):
print("I am a guitar")
piano = Instrument.piano
trumpet = Instrument.trumpet
guitar = Instrument.guitar
my_piano = Instrument(piano)
my_piano.play()
#... and others
您将未绑定的类方法传递给工具的__init__
,然后在play
中在self
上调用该方法。
您甚至可以通过创建独立功能来扩展可用的乐器
def violin(self):
print("I am playing a violin")
my_violin = Instrument(violin)
my_violin.play()
但是上面显示的整个方法在python世界中确实没什么用处。
答案 2 :(得分:2)
如果您真的不想创建类层次结构,可以在enum
类中定义所有可能的类型,然后选择正确的方法。为了避免if
语句,您可以使用词典:
In [1]: import enum
In [2]: class InstrumentType(enum.Enum):
...: PIANO = 0
...: GUITAR = 1
...: TRUMPET = 2
...:
In [3]: class Instrument:
...: def __init__(self, type):
...: self.type = type
...: def piano(self):
...: print('Piano')
...: def guitar(self):
...: print('Guitar')
...: def trumpet(self):
...: print('Trumpet')
...: def play(self):
...: return {
...: InstrumentType.PIANO: self.piano,
...: InstrumentType.GUITAR: self.guitar,
...: InstrumentType.TRUMPET: self.trumpet
...: }.get(self.type, lambda: print('Not an instrument'))()
...:
In [4]: guitar = Instrument(InstrumentType.GUITAR)
In [5]: guitar.play()
Guitar
In [6]: unknown = Instrument('UNKNOWN')
In [7]: unknown.play()
Not an instrument