473,378 Members | 1,405 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,378 software developers and data experts.

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.

Sep 21 '06 #1
17 15749
Hello,

lm***@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/
Sep 21 '06 #2

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

Sep 21 '06 #3
Thanks for the reply.

I think there's a basic misunderstanding 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(measurement)
elif type == 'fish':
myanimal = fish(measurement)

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
Sep 21 '06 #4
At Thursday 21/9/2006 06:52, lm***@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 ("initializer" 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!
http://www.yahoo.com.ar/respuestas

Sep 21 '06 #5
At Thursday 21/9/2006 07:34, LorcanM wrote:
>I think there's a basic misunderstanding 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!
http://www.yahoo.com.ar/respuestas

Sep 21 '06 #6
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 misunderstanding 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(measurement)
elif type == 'fish':
myanimal = fish(measurement)

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/
Sep 21 '06 #7
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

Sep 21 '06 #8
Thanks a lot folks for all the help. Its a lot clearer now.

If I could summarise my original misunderstanding about inheritance:

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

This is clearly not right - the misunderstanding 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.

Sep 21 '06 #9
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

Sep 21 '06 #10

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

Sep 21 '06 #11
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 'o****@xiludom.gro'.split('@')])"
Sep 21 '06 #12
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(object):
__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_type(cls, viewtype):
cls._viewtypes[viewtype.__name__] = viewtype

def get_view(self, typename, *args, **kw):
if isinstance(typename, 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(type):
def __init__(cls, classname, bases, dic):
World.register_view_type(cls)

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

class SomeWorldView(WorldView):
def __init__(self, world, foo, parrot=False):
WorldView.__init__(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 DelegateWorldView(WorldView):
def __init__(self, world):
WorldView.__init__(self, world)

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

# automagically delegate other stuff:
def __getattr__(self, name):
return getattr(self.world, name)

HTH

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Sep 21 '06 #13
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

Sep 21 '06 #14
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 "Undistributed Middle is indeed a fallacy"

;)

Regards,
Jordan

Sep 21 '06 #15
At Thursday 21/9/2006 09:14, Bruno Desthuilliers 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.
Yes, but trying to explain that to a beginner would just make things
worse... You must grab the inheritance concept first.

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!
http://www.yahoo.com.ar/respuestas

Sep 21 '06 #16
Thanks Bruno,

That is a more natural way to do it. The code looks a lot cleaner now.
Lorcan.

Sep 22 '06 #17
Gabriel Genellina wrote:
At Thursday 21/9/2006 09:14, Bruno Desthuilliers 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.

Yes, but trying to explain that to a beginner would just make things
worse...
Agreed. But this newsgroup is not only read by beginners, and the last
part of your statement happens to be false. The first part is ok, and
would have been enough IMHO.
You must grab the inheritance concept first.
Mmm... It's clear that the OP didn't get the concept right...

OTHO, inheritance (not subtyping...) is a very overrated concept IMHO
and really not central to OO - at least with dynamically typed languages
(or using type inference). It's in fact nothing more than a special case
of composition/delegation. What's really important here is polymorphic
dispatch, which shouldn't (and, in Python, doesn't) rely on
implementation inheritance.

I really think that insisting on implementation inheritance is the wrong
way to teach OO. But I may not be a good teacher !-)
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Sep 22 '06 #18

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

10
by: Scott Brady Drummonds | last post by:
Hi, everyone, I'm still learning Python as I develop a medium-sized project. From my previous experience with C++, I've burnt into my mind the notion of information hiding. I'm having trouble...
10
by: Jeff Grills | last post by:
I am an experienced C++ programmer with over 12 years of development, and I think I know C++ quite well. I'm changing jobs at the moment, and I have about a month between leaving my last job and...
8
by: dwok | last post by:
I have been wondering this for a while now. Suppose I have a class that contains some private member variables. How should I access the variables throughout the class? Should I use properties that...
1
by: Joseph Turian | last post by:
I'm having a little difficultly with inheritance. I want to have a class "SubT" inherit from class "T". SubT contains all the information in T, plus a little more based upon the member variables...
9
by: Richard Lewis Haggard | last post by:
What is the logic for dropping the C++ prepending of 'm_' from member variables? Has there been a consensus developed on how to discriminate between class members and automatic temp variables? --...
8
by: David Veeneman | last post by:
Should a member variable be passed to a private method in the same class as a method argument, or should the method simply call the member variable? For years, I have passed member variables to...
13
by: Henri.Chinasque | last post by:
Hi all, I am wondering about thread safety and member variables. If I have such a class: class foo { private float m_floater = 0.0; public void bar(){ m_floater = true; }
17
by: Juha Nieminen | last post by:
As we know, the keyword "inline" is a bit misleading because its meaning has changed in practice. In most modern compilers it has completely lost its meaning of "a hint for the compiler to inline...
4
by: aaragon | last post by:
Hi everyone, I have a linking error when using gcc4.2 and static member variables. The class template definition is something around the following: template<> class Element<L2_t: public...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.