Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
118 views
in Technique[技术] by (71.8m points)

Simple python inheritance

class Animal(object):
    def __init__(self, nlegs=4):
        print '__init__ Animal'
        self.nlegs = nlegs

class Cat(Animal):
    def __init__(self, talk='meow'):
        print '__init__ Cat'
        self.talk = talk

class Dog(Animal):
    def __init__(self, talk='woof'):
        print '__init__ Dog'
        self.talk = talk
  1. Why does my cat tom = Cat() not have an nlegs attribute?
  2. Should we explicitly call Animal.__init__() from within Cat.__init__, or should we be doing something more fancy, say, with super?
  3. What about if I want to create a cat with 5 legs, do I need to add additional arguments to the Cat.__init__ interface?
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

To build on what everyone else has said, yes, you'll need to call the parent's __init__ method.

It's generally best to use super. However, in certain cases (particularly when you're inheriting from multiple classes) it can be a big gotcha. I'll avoid going into detail, there are no shortage of various articles which discuss it. (Also, there are some oddities with some of the other "special" functions. For example, you can do super(SomeCls, self).__getitem__(5) but super(SomeCls, self)[5] won't work.)

As a simplistic example of why it's a good idea to use it, you could make Dog and Cat inherit from Mammal (which inherits from Animal) and not have to change places in your code other than which class Dog and Cat inherit from.

As for why your tom instance doesn't have tom.nlegs, it's because you haven't called Animal's __init__ method.

Also remember that not everything needs to be set at initialization time. For this example, it makes more sense not to set things like nlegs in the __init__ method. Instead, just set it directly in the class. E.g.

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

Basically, if something is likely to change from instance to instance (e.g. the color of the cat) or needs to be done at initialization (e.g. opening a file), then it probably should be set in __init__.

Otherwise, if it's something we want to be the same for any instance of the class, it can be cleaner to set it directly in the class definition.

Also, attributes set this way will be available to documentation tools (e.g. the built-in help function), whereas attributes set at initialization won't be.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...