简单的Python继承
class Animal(object):
def __init__(self, nlegs=4):
self.nlegs = nlegs
class Cat(Animal):
def __init__(self, talk='meow'):
self.talk = talk
class Dog(Animal):
def __init__(self, talk='woof'):
self.talk = talk
1. 为什么我的猫 tom = Cat() 没有 nlegs 这个属性?
2. 我们应该在 Cat.__init__ 里面明确调用 Animal.__init__() 吗?还是应该在这里使用 super 呢?
3. 如果我们想要创建一只有5条腿的猫,应该在 Cat.__init__ 的接口中添加额外的参数吗?
相关问题:
3 个回答
你需要查看一下Python的文档,关于super()这个函数。举个例子,通常你在写Cat.__init__()这个方法的时候,开头(或者结尾)会调用一下super(Cat, self).__init__(<任何参数>)。
使用 super:
class Cat(Animal):
def __init__(self, talk='meow', num_legs=4):
print 'Hay cat'
self.talk = talk
super(Cat, self).__init__(num_legs)
tom = Cat() #tom is a normal cat
bob = Cat('Nyan', 3) #bob is a japanese defective cat
接着大家说的内容,没错,你需要调用父类的 __init__ 方法。
一般来说,使用 super 是比较好的选择。不过在某些情况下(特别是当你从多个类继承时),这可能会带来一些麻烦。我就不详细说了,网上有很多关于这个的文章可以参考。还有一些其他“特殊”函数也有些奇怪的地方。例如,你可以用 super(SomeCls, self).__getitem__(5) 来获取值,但 super(SomeCls, self)[5] 就不行。
举个简单的例子,说明为什么使用 super 是个好主意。你可以让 Dog 和 Cat 继承自 Mammal(而 Mammal 又继承自 Animal),这样在代码中只需要改变 Dog 和 Cat 继承的类,而不需要其他改动。
至于为什么你的 tom 实例没有 tom.nlegs,是因为你没有调用 Animal 的 __init__ 方法。
另外要记住,并不是所有东西都需要在初始化时设置。对于这个例子,像 nlegs 这样的属性在 __init__ 方法中设置其实没必要。可以直接在类中设置。例如:
class Mammal(object):
nlimbs = 4
def __init__(self):
print "I'm a mammal!"
class Cat(Mammal):
def __init__(self, color="calico"):
self.color = color
super(Cat, self).__init__()
print "I have {0} legs I am {1}".format(self.nlimbs, self.color)
class FiveLeggedCat(Cat):
nlimbs = 5
基本上,如果某个属性可能在不同实例之间变化(比如猫的颜色),或者需要在初始化时做(比如打开一个文件),那么它应该在 __init__ 中设置。
否则,如果是我们希望在类的任何实例中都保持一致的属性,直接在类定义中设置会更简洁。
此外,这种方式设置的属性会被文档工具(比如内置的 help 函数)识别,而在初始化时设置的属性则不会。