Can I inherit member variables?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • lm401@cam.ac.uk

    Can I inherit member variables?

    I'm trying to work with the following idea:

    class animal:
    def __init__(self, weight, colour):
    self.weight = weight
    self.colour = colour


    class bird(animal):
    def __init__(self, wingspan):
    self.wingspan = wingspan
    print self.weight, self.colour, self.wingspan

    class fish(animal):
    def __init__(self, length):
    self.length = length
    print self.weight, self.colour, self.length


    So basically I have a base class (animal) that has certain attributes.
    When animal is inherited by a specific instance, further attributes are
    added, but I need to have access to the original attributes (weight,
    colour). When I run my code from within the derived class, self.weight
    and self.colour are not inherited (although methods are inherited as I
    would have expected).

    It seems from reading the newsgroups that a solution might be to
    declare weight and colour as global variables in the class animal:

    class animal:
    pass

    myanimal = animal()
    myanimal.weight = 4
    myanimal.colour = 'blue'

    But this is not exactly what I want to do.

    I'm not very experienced with OOP techniques, so perhaps what I'm
    trying to do is not sensible. Does Python differ with regard to
    inheritance of member variables from C++ and Java?

    Thanks for any help,



    Lorcan.

  • Benjamin Niemann

    #2
    Re: Can I inherit member variables?

    Hello,

    lm401@cam.ac.uk wrote:
    I'm trying to work with the following idea:
    >
    class animal:
    def __init__(self, weight, colour):
    self.weight = weight
    self.colour = colour
    >
    >
    class bird(animal):
    def __init__(self, wingspan):
    self.wingspan = wingspan
    print self.weight, self.colour, self.wingspan
    >
    class fish(animal):
    def __init__(self, length):
    self.length = length
    print self.weight, self.colour, self.length
    >
    >
    So basically I have a base class (animal) that has certain attributes.
    When animal is inherited by a specific instance, further attributes are
    added, but I need to have access to the original attributes (weight,
    colour). When I run my code from within the derived class, self.weight
    and self.colour are not inherited (although methods are inherited as I
    would have expected).
    You'll have to invoke the __init__ method of the superclass, this is not
    done implicitly. And you probably want to add the weight and colour
    attributes to your subclass in order to pass these to the animal
    constructor.

    class fish(animal):
    def __init__(self, length, weight, colour):
    animal.__init__ (self, weight, colour)
    self.length = length
    print self.weight, self.colour, self.length


    HTH

    --
    Benjamin Niemann
    Email: pink at odahoda dot de
    WWW: http://pink.odahoda.de/

    Comment

    • MonkeeSage

      #3
      Re: Can I inherit member variables?


      l...@cam.ac.uk wrote:
      When I run my code from within the derived class, self.weight
      and self.colour are not inherited (although methods are inherited as I
      would have expected).
      Animal is never initialized and you're not passing weight and color
      into it anyway. You need something like:

      class animal: # (object): # <- new-style class
      def __init__(self, weight, colour):
      self.weight = weight
      self.colour = colour

      class bird(animal):
      def __init__(self, weight, color, wingspan):
      #super(bird, self).__init__( weight, color) # <- new-style init
      animal.__init__ (self, weight, color) # <- old-style init
      self.wingspan = wingspan
      print self.weight, self.colour, self.wingspan

      class fish(animal):
      def __init__(self, weight, color, length):
      #super(fish, self).__init__( weight, color)
      animal.__init__ (self, weight, color)
      self.length = length
      print self.weight, self.colour, self.length

      HTH,
      Jordan

      Comment

      • LorcanM

        #4
        Re: Can I inherit member variables?

        Thanks for the reply.

        I think there's a basic misunderstandin g about the nature of
        inheritance on my side.

        What I want to do is instantiate the sub class (derived class) from
        within the animal class. I then expect the sub class to have inherited
        some basic properties that it knows it has (weight, colour). If I can
        expand the example I gave previously to try to make this a little
        clearer:

        class animal:
        def __init__(self, weight, colour):
        self.weight = weight
        self.colour = colour

        def describeMyself( self, type, measurement):
        if type == 'bird':
        myanimal = bird(measuremen t)
        elif type == 'fish':
        myanimal = fish(measuremen t)

        class bird(animal):
        def __init__(self, wingspan):
        self.wingspan = wingspan
        print "I'm a bird, weight %s, colour %s, wingspan %s" %
        (self.weight, self.colour, self.wingspan)

        class fish(animal):
        def __init__(self, length):
        self.length = length
        print "I'm a fish, weight %s, colour %s, length %s" % (self.weight,
        self.colour, self.length)


        It seems from what you say that the attributes (member variables) will
        have to be passed forward explicitly like any other function call. This
        of course is sensible, 'bird' or 'fish' are not tied to a specific
        instance of 'animal' when they are instantiated.

        Thanks for the help,


        Lorcan.


        Benjamin Niemann wrote:

        You'll have to invoke the __init__ method of the superclass, this is not
        done implicitly. And you probably want to add the weight and colour
        attributes to your subclass in order to pass these to the animal
        constructor.
        >
        class fish(animal):
        def __init__(self, length, weight, colour):
        animal.__init__ (self, weight, colour)
        self.length = length
        print self.weight, self.colour, self.length
        >

        Comment

        • Gabriel Genellina

          #5
          Re: Can I inherit member variables?

          At Thursday 21/9/2006 06:52, lm401@cam.ac.uk wrote:
          >class animal:
          def __init__(self, weight, colour):
          self.weight = weight
          self.colour = colour
          >
          >
          >class bird(animal):
          def __init__(self, wingspan):
          self.wingspan = wingspan
          print self.weight, self.colour, self.wingspan
          >
          >class fish(animal):
          def __init__(self, length):
          self.length = length
          print self.weight, self.colour, self.length
          >
          >
          >So basically I have a base class (animal) that has certain attributes.
          >When animal is inherited by a specific instance, further attributes are
          >added, but I need to have access to the original attributes (weight,
          >colour). When I run my code from within the derived class, self.weight
          >and self.colour are not inherited (although methods are inherited as I
          >would have expected).
          You have to call the base __init__ too. If a bird is some kind of
          animal, it has a weight and a colour, and you have to provide them too:

          class bird(animal):
          def __init__(self, weight, colour, wingspan):
          animal.__init__ (self, weight, colour)
          self.wingspan = wingspan
          print self.weight, self.colour, self.wingspan
          >It seems from reading the newsgroups that a solution might be to
          >declare weight and colour as global variables in the class animal:
          You can declare them as class attributes inside animal; this way they
          act like a default value for instance attributes.

          class animal:
          weight = 0
          colour = ''
          ...
          >I'm not very experienced with OOP techniques, so perhaps what I'm
          >trying to do is not sensible. Does Python differ with regard to
          >inheritance of member variables from C++ and Java?
          They are not called "member variables" but "instance attributes".
          They *are* inherited [1] but you have to set their value somewhere.
          Any object can hold virtually any attribute - this is *not* usually
          determined by the object's class.
          Base constructors ("initialize r" actually) are *not* invoked
          automatically, so you must call them explicitely.

          Read the Python Tutorial, it's easy and will teach you a lot of
          things about the language. You can read it online at
          <http://docs.python.org/tut/tut.html>

          [1] kinda... remember that classes don't determine the available
          attributes; class attributes are inherited, and any attribute you set
          on an instance will be accessible by any method of the object, even
          above in the hierarchy.



          Gabriel Genellina
          Softlab SRL





          _______________ _______________ _______________ _____
          Preguntá. Respondé. Descubrí.
          Todo lo que querías saber, y lo que ni imaginabas,
          está en Yahoo! Respuestas (Beta).
          ¡Probalo ya!


          Comment

          • Gabriel Genellina

            #6
            Re: Can I inherit member variables?

            At Thursday 21/9/2006 07:34, LorcanM wrote:
            >I think there's a basic misunderstandin g about the nature of
            >inheritance on my side.
            >
            >What I want to do is instantiate the sub class (derived class) from
            >within the animal class. I then expect the sub class to have inherited
            >some basic properties that it knows it has (weight, colour). If I can
            >expand the example I gave previously to try to make this a little
            >clearer:
            As an analogy: a certain animal, a given individual, is of a kind
            "from birth". You don't have an abstract, unshaped, animal, that by
            some kind of magic later becomes a bird, or a mammal...
            When you construct an object instance, it is of a certain type from
            that precise moment, and you can't change that afterwards.
            So, you construct a bird, which is a kind of animal (class
            inheritance is the way of modelling that "is a kind of" relationship).

            Hope it becomes clearer now.



            Gabriel Genellina
            Softlab SRL





            _______________ _______________ _______________ _____
            Preguntá. Respondé. Descubrí.
            Todo lo que querías saber, y lo que ni imaginabas,
            está en Yahoo! Respuestas (Beta).
            ¡Probalo ya!


            Comment

            • Benjamin Niemann

              #7
              Re: Can I inherit member variables?

              LorcanM wrote:
              Benjamin Niemann wrote:
              >
              >You'll have to invoke the __init__ method of the superclass, this is not
              >done implicitly. And you probably want to add the weight and colour
              >attributes to your subclass in order to pass these to the animal
              >constructor.
              >>
              >class fish(animal):
              > def __init__(self, length, weight, colour):
              > animal.__init__ (self, weight, colour)
              > self.length = length
              > print self.weight, self.colour, self.length
              >
              Thanks for the reply.
              >
              I think there's a basic misunderstandin g about the nature of
              inheritance on my side.
              >
              What I want to do is instantiate the sub class (derived class) from
              within the animal class. I then expect the sub class to have inherited
              some basic properties that it knows it has (weight, colour). If I can
              expand the example I gave previously to try to make this a little
              clearer:
              >
              class animal:
              def __init__(self, weight, colour):
              self.weight = weight
              self.colour = colour
              >
              def describeMyself( self, type, measurement):
              if type == 'bird':
              myanimal = bird(measuremen t)
              elif type == 'fish':
              myanimal = fish(measuremen t)
              >
              class bird(animal):
              def __init__(self, wingspan):
              self.wingspan = wingspan
              print "I'm a bird, weight %s, colour %s, wingspan %s" %
              (self.weight, self.colour, self.wingspan)
              >
              class fish(animal):
              def __init__(self, length):
              self.length = length
              print "I'm a fish, weight %s, colour %s, length %s" % (self.weight,
              self.colour, self.length)
              Do you really want one animal instance to act both as bird and fish?
              Wouldn't it be more sensible to instanciate either bird or fish (animal
              being what is called an abstract class in other OOP languages)? bird and
              fish would then have their own implementation of describeMyself( ) with
              the 'print "I'm a..."' statement.

              I must admit that I don't really understand what you are trying to
              achieve...


              --
              Benjamin Niemann
              Email: pink at odahoda dot de
              WWW: http://pink.odahoda.de/

              Comment

              • MonkeeSage

                #8
                Re: Can I inherit member variables?

                Hi Lorcan,

                Mabye thinking of it like this will help: birds and fishes (I love that
                word, even if it is incorrect) can _do_ all the things that all animals
                have in common: eat, drink, die, reproduce, &c; but that is generic.

                class animal(object):
                def eat(self, food): pass
                ...
                class bird(animal): pass
                class fish(animal): pass

                If you want to talk about a specific bird or fish, then you have to say
                more than just that it is an animal. Now, if all animals have a weight
                and a color, but not all have the same weight or color, then you want
                to say that this bird or fish is an animal which is colored X and
                weighes Y.

                class animal(object):
                def __init__(self, weight, colour):
                self.weight = weight
                self.colour = colour
                class bird(animal): pass # __init__ from animal is called implicitly
                class fish(animal): pass

                Now what if a bird and a fish have other attributes that not all
                animals share (or at least specialized versions)? Well then you need to
                say this bird is an animal which is colored X and weighs Y, but unlike
                other animals, has a wingspan or length of Z.

                class animal(object):
                def __init__(self, weight, colour):
                self.weight = weight
                self.colour = colour
                class bird(animal):
                # override __init__ so we can say what _this_ animal is like
                def __init__(self, weight, color, wingspan):
                super(bird, self).__init__( weight, color)
                self.wingspan = wingspan
                class fish(animal):
                def __init__(self, weight, color, length):
                super(fish, self).__init__( weight, color)
                self.length = length

                Does this make more sense?

                Regards,
                Jordan

                Comment

                • LorcanM

                  #9
                  Re: Can I inherit member variables?

                  Thanks a lot folks for all the help. Its a lot clearer now.

                  If I could summarise my original misunderstandin g about inheritance:

                  I belived that a sub class inherited a *specific instance* of the super
                  class.

                  This is clearly not right - the misunderstandin g arose as I was
                  instantiating the super class from within the base class. As people
                  have pointed out it seems strange to instantiate an 'animal' and then
                  only later decide that it is a 'fish' or a 'bird'. Obviously my code is
                  an analogy to the problem I'm tackling. What I'm doing is a bit more
                  abstract: I'm instantiating a 'world' (as a super class) and then
                  various 'worldviews' as sub-classes. The 'worldviews' must know about
                  various aspects of the 'world' from which they are instantiated to be
                  able to do what they need to do (as the 'bird' needs to know about
                  'weight' and 'colour' to be able to describe itself).

                  Passing these aspects forward to the constructor of the sub class is
                  the solution I've implemented and it works and looks sensible.

                  Thanks again to all,


                  Lorcan.

                  Comment

                  • bearophileHUGS@lycos.com

                    #10
                    Re: Can I inherit member variables?

                    MonkeeSage:

                    If you have multiple inheritance do you need the old style init anyway?

                    class Animal1(object) :
                    def __init__(self, weight, colour):
                    self.weight = weight
                    self.colour = colour

                    class Animal2(object) :
                    def __init__(self, name):
                    self.name = name

                    class Bird(Animal1, Animal2):
                    def __init__(self, weight, color, wingspan, name):
                    super(Bird, self).__init__( weight, color) # Animal1
                    Animal2.__init_ _(self, name)
                    self.wingspan = wingspan
                    print self.weight, self.colour, self.wingspan, self.name

                    al = Bird(12, "White", 2, "Albatross" )

                    Bye,
                    bearophile

                    Comment

                    • MonkeeSage

                      #11
                      Re: Can I inherit member variables?


                      bearophileH...@ lycos.com wrote:
                      If you have multiple inheritance do you need the old style init anyway?
                      I guess so, I'm not really sure. This page
                      <http://fuhm.net/super-harmful/talks about super() and MRO and such,
                      but I have only glanced over it the other day. I will read it more
                      fully sometime. I tend not to use multiple inheritance very often, and
                      when I do I usually don't need to initialize the superclasses. So I've
                      never really thought about it or researched into it. Someone smarter
                      than me would probably know (hey wait a second -- you're smarter than
                      me! I've seen your code golf score, buddy! ;) ).

                      Regards,
                      Jordan

                      Comment

                      • Bruno Desthuilliers

                        #12
                        Re: Can I inherit member variables?

                        Gabriel Genellina wrote:
                        (snip)
                        When you construct an object instance, it is of a certain type from that
                        precise moment, and you can't change that afterwards.
                        Err... Actually, in Python, you can. It's even a no-brainer.

                        (snip)

                        --
                        bruno desthuilliers
                        python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
                        p in 'onurb@xiludom. gro'.split('@')])"

                        Comment

                        • Bruno Desthuilliers

                          #13
                          Re: Can I inherit member variables?

                          LorcanM wrote:
                          (snip)
                          What I'm doing is a bit more
                          abstract: I'm instantiating a 'world' (as a super class) and then
                          various 'worldviews' as sub-classes. The 'worldviews' must know about
                          various aspects of the 'world' from which they are instantiated to be
                          able to do what they need to do
                          Mmmm... I suspect that you're falling into the good'ole trap of abusing
                          inheritance here. The fact that Worlview instances needs to know about a
                          World instance is usually modeled by composition, ie WorldViews are
                          instanciated with a world instance and keep a reference to it:

                          class World(object):
                          pass

                          class WorldView(objec t):
                          __metaclass__ = WorldViewMeta
                          def __init__(self, world, *args, **kw):
                          self.world = world

                          world = World()
                          wv = WorldView(world )


                          If you need/want to get WorldViews from the world itself, it's not much
                          more difficult:

                          class World(object):
                          def get_view(self, viewtype):
                          return viewtype(self)


                          world = World()
                          wv = world.get_view( WorldView)


                          And if you really need/want to be able to do the same thing but with the
                          WorldView name instead of the class itself:

                          class World(object):
                          _viewtypes = {}

                          @classmethod
                          def register_view_t ype(cls, viewtype):
                          cls._viewtypes[viewtype.__name __] = viewtype

                          def get_view(self, typename, *args, **kw):
                          if isinstance(type name, basestring):
                          return self._viewtypes[typename](self, *args, **kw)
                          else: # assume it's the class
                          return typename(self, *args, **kw)

                          def dothis(self):
                          return "dothis"

                          def dothat(self, bar):
                          return bar + bar

                          class WorldViewMeta(t ype):
                          def __init__(cls, classname, bases, dic):
                          World.register_ view_type(cls)

                          class WorldView(objec t):
                          __metaclass__ = WorldViewMeta
                          def __init__(self, world, *args, **kw):
                          self.world = world

                          class SomeWorldView(W orldView):
                          def __init__(self, world, foo, parrot=False):
                          WorldView.__ini t__(self, world)
                          self.foo = foo
                          self.parrot = parrot

                          world = World()
                          some_view = world.get_view( "SomeWorldView" , 42, parrot=True)
                          # or
                          some_view = world.get_view( SomeWorldView, 42, parrot=True)


                          Also, if you want to be able to use the WorldViews like it was the world
                          itself, you can easily delegate:

                          class DelegateWorldVi ew(WorldView):
                          def __init__(self, world):
                          WorldView.__ini t__(self, world)

                          # 'override' World.dothat:
                          def dothat(self, bar):
                          bar = bar * 3
                          return self.world.doth at(bar)

                          # automagically delegate other stuff:
                          def __getattr__(sel f, name):
                          return getattr(self.wo rld, name)

                          HTH

                          --
                          bruno desthuilliers
                          python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
                          p in 'onurb@xiludom. gro'.split('@')])"

                          Comment

                          • Wildemar Wildenburger

                            #14
                            Re: Can I inherit member variables?

                            Bruno Desthuilliers wrote:
                            Gabriel Genellina wrote:
                            >When you construct an object instance, it is of a certain type from that
                            >precise moment, and you can't change that afterwards.
                            >
                            Err... Actually, in Python, you can. It's even a no-brainer.
                            Oh yeah, let's confuse the newbie, shall we :)

                            The art of teaching lies in what you *don't* tell the teachee in the
                            first run.
                            But factually, you're right. In the course of this OO lesson, however:
                            ssshhhhhhhh!

                            ;)
                            wildemar

                            Comment

                            • MonkeeSage

                              #15
                              Re: Can I inherit member variables?

                              Ps. Aristotle can rest easy tonight:

                              class mortal(object): pass
                              class man(mortal): pass
                              Socrates = man()
                              all_men = mortal()
                              if Socrates == all_men:
                              print "Socrates == all_man"
                              else:
                              print "Undistribu ted Middle is indeed a fallacy"

                              ;)

                              Regards,
                              Jordan

                              Comment

                              Working...