我在Python类(classa
)中包含了一些功能。 classa
继承自另一个班级supera
。
除了我想从classa
继承之外,我想要与superb
完全相同的功能。
我可以将类classa
复制到新的类classb
,然后更改classb
的超类,但显然这非常俗气,维护很头疼,而且我很确定有更好的方法 - 谁能告诉我它是什么?
编辑:到目前为止,感谢您的回答。我应该首先说我的classa
在其方法中调用super来调用supera
方法。在将mixins视为一种选择时,这似乎有一些意义
答案 0 :(得分:4)
如果没有一个方法需要调用super()
,可以使用Python的多重继承来完成。
class Dog(object):
name = "Spot"
class Cat(object):
name = "Whiskers"
class SpeakingAnimalMixin(object):
def speak(self):
print "My name is", self.name, "and I can speak!"
class SpeakingDog(SpeakingAnimalMixin, Dog):
pass
class SpeakingCat(SpeakingAnimalMixin, Cat):
pass
SpeakingDog().speak()
我的名字是Spot,我可以说!
如果确实需要从方法中调用super()
,则需要动态创建类。这样可以正常工作,但生成的类的名称不太有用,IDE和其他静态分析工具可能没那么有用。
您可以使用函数创建类,将超类作为参数传递:
def make_speaking_animal_class(SpeechlessAnimal):
class SpeakingAnimal(SpeechlessAnimal):
def get_name(self):
return "Speaking " + super(SpeakingAnimal, self).get_name()
def speak(self):
print "My name is", self.get_name()
return SpeakingAnimal
class Dog(object):
def get_name(self):
return "Spot"
class Cat(object):
def get_name(self):
return "Whiskers"
SpeakingDog = make_speaking_animal_class(Dog)
SpeakingCat = make_speaking_animal_class(Cat)
SpeakingCat().speak()
我的名字是Speaking Whiskers
但是如上所述,班级的__name__
属性可能不是您所期望的。
print SpeakingDog
print SpeakingDog()
<class '__main__.SpeakingAnimal'>
<__main__.SpeakingAnimal object at 0x1004a3b50>
您可以自行为其分配唯一的__name__
属性来解决此问题:
SpeakingDog.__name__ = 'SpeakingDog'
print SpeakingDog
<class '__main__.SpeakingDog'>
(感谢Andrew Jaffe在答案中建议这一点,但他删除了它。)
还有另一种动态创建类的方法,但除非你需要,否则我不鼓励你使用它;它甚至不太清楚。除了确定对象类的主要内容之外,The type
function还有第二种用途:它可用于动态创建新类。
以这种方式使用时,type
函数有三个参数:
name
,新课程的__name__
。bases
,新类将继承的基类元组。dict
,一个包含新类将具有的方法和属性的字典。您可以像这样使用它:
def make_speaking_animal_class(SpeechlessAnimal, name):
def get_name(self):
return "Speaking " + super(SpeakingAnimal, self).get_name()
def speak(self):
print "My name is", self.get_name()
bases = (SpeechlessAnimal,)
# We need to define SpeakingAnimal in a variable so that get_name can refer
# to it for the super() call, otherwise we could just return it directly.
SpeakingAnimal = type(name, bases, {
'get_name': get_name,
'speak': speak
})
return SpeakingAnimal
class Dog(object):
def get_name(self):
return "Spot"
class Cat(object):
def get_name(self):
return "Whiskers"
SpeakingDog = make_speaking_animal_class(Dog, 'SpeakingDog')
SpeakingCat = make_speaking_animal_class(Cat, 'SpeakingCat')
SpeakingDog().speak()
SpeakingCat().speak()
我的名字是Speaking Spot
我的名字是Speaking Whiskers