Inheritance question

T

Tzury Bar Yochay

given two classes:

class Foo(object):
def __init__(self):
self.id = 1

def getid(self):
return self.id

class FooSon(Foo):
def __init__(self):
Foo.__init__(self)
self.id = 2

def getid(self):
a = Foo.getid()
b = self.id
return '%d.%d' % (a,b)

While my intention is to get 1.2 I get 2.2
I would like to know what would be the right way to yield the expected
results
 
J

Jeff

Rather than use Foo.bar(), use this syntax to call methods of the
super class:

super(ParentClass, self).method()
 
J

John Machin

given two classes:

class Foo(object):
def __init__(self):
self.id = 1

def getid(self):
return self.id

class FooSon(Foo):
def __init__(self):
Foo.__init__(self)
self.id = 2

def getid(self):
a = Foo.getid()
b = self.id
return '%d.%d' % (a,b)

While my intention is to get 1.2 I get 2.2
I would like to know what would be the right way to yield the expected
results

Post the code that you actually executed. What you have shown lacks
the code to execute it ... but the execution will fail anyway:

a = Foo.getid()
TypeError: unbound method getid() must be called with Foo instance as
first argument (got nothing instead)
 
T

Tzury Bar Yochay

Post the code that you actually executed. What you have shown lacks
the code to execute it ... but the execution will fail anyway:

    a = Foo.getid()
TypeError: unbound method getid() must be called with Foo instance as
first argument (got nothing instead)
sorry, it should have been:
a = Foo.getid(self)
instead of
a = Foo.getid()
 
T

Tzury Bar Yochay

Rather than use Foo.bar(), use this syntax to call methods of the
super class:

super(ParentClass, self).method()

Hi Jeff,
here is the nw version which cause an error

class Foo(object):
def __init__(self):
self.id = 1

def getid(self):
return self.id

class FooSon(Foo):
def __init__(self):
Foo.__init__(self)
self.id = 2

def getid(self):
a = super(Foo, self).getid()
b = self.id
return '%d.%d' % (a,b)


FooSon().getid()


Traceback (most recent call last):
File "a.py", line 19, in <module>
FooSon().getid()
File "a.py", line 14, in getid
a = super(Foo, self).getid()
AttributeError: 'super' object has no attribute 'getid'
 
A

Anthony

While my intention is to get 1.2 I get 2.2
I would like to know what would be the right way to yield the expected
results

Is this what you want?

class Foo(object):
def __init__(self):
self.id = 1
def getid(self):
return self.id

class FooSon(Foo):
def __init__(self):
Foo.__init__(self)
self.id = 2
def getid(self):
a = Foo().getid()
b = self.id
return '%d.%d' % (a,b)
'1.2'

Best wishes,
Anthony
 
T

Tzury Bar Yochay

Is this what you want?

class Foo(object):
    def __init__(self):
        self.id = 1
    def getid(self):
        return self.id

class FooSon(Foo):
    def __init__(self):
        Foo.__init__(self)
        self.id = 2
    def getid(self):
        a = Foo().getid()
        b = self.id
        return '%d.%d' % (a,b)


'1.2'

Best wishes,
Anthony

I wish it was that simple but 'a = Foo().getid()' is actually creating
a new instance of Foo whereas I want the data of the Foo instanced by
__init__ of FooSon().

what I am actually trying to do is to build a set of classes which
handle different type of binary messages coming from the network.

a base message which handles its basic data parts (src, dst, etc.) and
extending it per message type. thus I looked for a way to get the
child calling super for parsing the super's prats and then having the
child parsing its additional details.
 
G

Gerard Flanagan

Hi Jeff,
here is the nw version which cause an error

class Foo(object):
def __init__(self):
self.id = 1

def getid(self):
return self.id

class FooSon(Foo):
def __init__(self):
Foo.__init__(self)
self.id = 2

def getid(self):
a = super(Foo, self).getid()
b = self.id
return '%d.%d' % (a,b)

FooSon().getid()

Traceback (most recent call last):
File "a.py", line 19, in <module>
FooSon().getid()
File "a.py", line 14, in getid
a = super(Foo, self).getid()
AttributeError: 'super' object has no attribute 'getid'

Use the child class when calling super:

--------------------------------------
class Foo(object):
def __init__(self):
self.id = 1

def getid(self):
return self.id

class FooSon(Foo):
def __init__(self):
Foo.__init__(self)
self.id = 2

def getid(self):
a = super(FooSon, self).getid()
b = self.id
return '%d.%d' % (a,b)

print FooSon().getid()
 
A

Anthony

I wish it was that simple but 'a = Foo().getid()' is actually creating
a new instance of Foo whereas I want the data of the Foo instanced by
__init__ of FooSon().

I don't think Foo.__init__(self) creates an instance of the Foo
class. If you want FooSon to create an instance of Foo, try:

class FooSon(Foo):
def __init__(self):
self.foo = Foo()
self.id = 2
def getid(self):
a = self.foo.getid()
b = self.id
return '%d.%d' % (a,b)
'1.2'

Or change "self.id" in Foo to something else, e.g., "self.id_foo".

Does that help?

Anthony
 
B

Brian Lane

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Gerard said:
Use the child class when calling super:

--------------------------------------
class Foo(object):
def __init__(self):
self.id = 1

def getid(self):
return self.id

class FooSon(Foo):
def __init__(self):
Foo.__init__(self)
self.id = 2

def getid(self):
a = super(FooSon, self).getid()
b = self.id
return '%d.%d' % (a,b)

print FooSon().getid()
--------------------------------------

That still doesn't do what he's trying to do.

The problem here is that you only have one instance. self refers to it,
so when you set self.id in the super you have set the instance's id to
1. When you set it to 2 after calling the super's __init__ you are now
setting the *same* variable to a 2.

Basically, you can't do what you are trying to do without using a
different variable, or keeping track of a separate instance for the
super instead of sub-classing it.

Brian

- --
- ---[Office 71.7F]--[Outside 33.2F]--[Server 99.5F]--[Coaster 68.7F]---
- ---[ KLAHOWYA WSF (366773110) @ 47 31.2076 -122 27.2249 ]---
Software, Linux, Microcontrollers http://www.brianlane.com
AIS Parser SDK http://www.aisparser.com
Movie Landmarks Search Engine http://www.movielandmarks.com

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (Darwin)
Comment: Remember Lexington Green!

iD8DBQFH6RwcIftj/pcSws0RArdpAJ9pCMjrkpBarHyQsl6hXEifj52giwCfXfKa
Ot/1a+NNOLN5LA4mxBtfpis=
=Yacu
-----END PGP SIGNATURE-----
 
H

Hrvoje Niksic

Tzury Bar Yochay said:
given two classes:

class Foo(object):
def __init__(self):
self.id = 1

def getid(self):
return self.id

class FooSon(Foo):
def __init__(self):
Foo.__init__(self)
self.id = 2

def getid(self):
a = Foo.getid()
b = self.id
return '%d.%d' % (a,b)

Try this:

class Foo(object):
def __init__(self):
self.__id = 1

def getid(self):
return self.__id

class FooSon(Foo):
def __init__(self):
Foo.__init__(self)
self.__id = 2

def getid(self):
a = Foo.getid(self)
b = self.__id
return '%d.%d' % (a,b)
'1.2'

While my intention is to get 1.2 I get 2.2 I would like to know what
would be the right way to yield the expected results

Either use the above "private" fields, or emulate them yourself by
renaming self.id to self.foo_id or self.foo_son_id, and exposing those
in the class. Or you can have a class-specific dict in each instance,
and so on.
 
H

Hrvoje Niksic

Brian Lane said:
Basically, you can't do what you are trying to do without using a
different variable,

....or abusing the __foo private identifier trick.
 
D

Diez B. Roggisch

Anthony said:
I don't think Foo.__init__(self) creates an instance of the Foo
class. If you want FooSon to create an instance of Foo, try:

You wrote:

a = Foo().getid()

Which indeed creates a *new* Foo-instance. So it's of no use to the OP.

Of course Foo.<method>(self) calls that method without creating a new
instance, which is the behavior one uses when invoking the constructor of
Foo inside FooSon.__init__. But that doesn't make your example any better.

Diez
 
E

Eric Brunel

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1



That still doesn't do what he's trying to do.

The problem here is that you only have one instance. self refers to it,
so when you set self.id in the super you have set the instance's id to
1. When you set it to 2 after calling the super's __init__ you are now
setting the *same* variable to a 2.

Basically, you can't do what you are trying to do without using a
different variable, or keeping track of a separate instance for the
super instead of sub-classing it.

If for any reason it's better to have the same attribute name, it might be
a case where a "pseudo-private" attribute - i.e. prefixed with __ - can be
handy:

--------------------------------------
class Foo(object):
def __init__(self):
self.__id = 1
def getid(self):
return self.__id

class FooSon(Foo):
def __init__(self):
Foo.__init__(self)
self.__id = 2
def getid(self):
a = super(FooSon, self).getid()
b = self.__id
return '%d.%d' % (a,b)

print FooSon().getid()
--------------------------------------

For an explanation, see here:
http://docs.python.org/ref/atom-identifiers.html

HTH
 
G

Gerard Flanagan

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1









That still doesn't do what he's trying to do.

Ah, I see. Maybe something like the following then?

--------------------------------------
class Foo(object):
def __init__(self):
self._id = [1]

def getid(self):
return '.'.join(str(i) for i in self._id)

class FooSon(Foo):
def __init__(self):
Foo.__init__(self)
self._id.append(2)

print FooSon().getid()
 
R

Robert Bossy

Hi,

I'm not sure what you're trying to actually achieve, but it seems that
you want an identificator for classes, not for instances. In this case,
setting the id should be kept out of __init__ since it is an instance
initializer: make id static and thus getid() a classmethod.
Furthermore, if you have several Foo subclasses and subsubclasses, etc.
and still want to use the same identificator scheme, the getid() method
would better be defined once for ever in Foo. I propose you the following:

<code>
class Foo(object):
id = 1

def getid(cls):
if cls == Foo: return str(cls.id)
return '%s.%d' % (cls.__bases__[0].getid(), cls.id) # get the
parent id and append its own id
getid = classmethod(getid)

class FooSon(Foo):
id = 2

class Bar(Foo):
id = 3

class Toto(Bar):
id = 1

# Show me that this works
for cls in [Foo, FooSon, Bar, Toto]:
inst = cls()
print '%s id: %s\n also can getid from an instance: %s\n' %
(cls.__name__, cls.getid(), inst.getid())
</code>

One advantage of this approach is that you don't have to redefine the
getid() method for each Foo child and descendent. Unfortunately, the
"cls.__bases__[0]" part makes getid() to work if and only if the first
base class is Foo or a subclass of Foo. You're not using multiple
inheritance, are you?

RB
 
C

castironpi

Hi,

I'm not sure what you're trying to actually achieve, but it seems that
you want an identificator for classes, not for instances. In this case,
setting the id should be kept out of __init__ since it is an instance
initializer: make id static and thus getid() a classmethod.
Furthermore, if you have several Foo subclasses and subsubclasses, etc.
and still want to use the same identificator scheme, the getid() method
would better be defined once for ever in Foo. I propose you the following:

<code>
class Foo(object):
    id = 1

    def getid(cls):
        if cls == Foo: return str(cls.id)
        return '%s.%d' % (cls.__bases__[0].getid(), cls.id) # get the
parent id and append its own id
    getid = classmethod(getid)

class FooSon(Foo):
    id = 2

class Bar(Foo):
    id = 3

class Toto(Bar):
    id = 1

# Show me that this works
for cls in [Foo, FooSon, Bar, Toto]:
    inst = cls()
    print '%s id: %s\n    also can getid from an instance: %s\n' %
(cls.__name__, cls.getid(), inst.getid())
</code>

One advantage of this approach is that you don't have to redefine the
getid() method for each Foo child and descendent. Unfortunately, the
"cls.__bases__[0]" part makes getid() to work if and only if the first
base class is Foo or a subclass of Foo. You're not using multiple
inheritance, are you?

RB

It is clear there are always two vectors is programmer thoughtspace:
class and instance, and that they are orthogonal, and even
orthonormal. Every (human-thought native) data structure can be
expressed as a sum of two vectors, scalar * unit, scalar * unit in a
particular order (cf. Gram-Schmidt), or a tuple. Writing code is
simply the specification of scalar and scalar.

Clearly the alphabet-space of programs ( symbol* ) contains (improper)
the alphabet-space of Python programs, (which) contains (proper) the
token-space of Python programs, (which) contains (proper) the grammar-
space of Python programs, yet but here we lose thought; do you think
in Python?

Python ignores some subset of distinctions we make in thought, and we
ignore some subset of distinctions Python require (w.c.)s. How do we
effectively communicate with it?

Order is a non-commutative relation. (a,b) did come from reality, but
does not fulfill Rab; conclude (a,b) did not come from reality; and R
is a truth relation. </lemma>

Conclude Rab is a scalar. Is a gram a pound? Is it two pounds?
Newton's zero-find method finds b given a and Rab. (Expected time to
zero pent). Do you think in Newton's method? Are functions scalars?
'''In the mid-20th century, some mathematicians decided that writing
"g o f" to mean "first apply f, then apply g" was too confusing and
decided to change notations. They wrote "xf" for "f(x)" and "xfg" for
"g(f(x))". This can be more natural and seem simpler than writing
functions on the left in some areas.''' - wikipedia.

Does anyone know category theory or pointless topology? My point in
asking, is if we can explain in a really easy way using those
establishments, to Python how we think, (several symbols, what when),
we would like it, assuming it likes us.

To effectively communicate with Python, what does the assumption that
'we want something', that 'there's a reward' exclude? Python wants to
reward programmers often enough. (Python + Usenet does!) Do we like
to be frustrated? What's good for us is good for Python. What
frustrates you the most?
 
T

Tzury Bar Yochay

Hi all,

I would like to thank you all for all the suggestions.
what I did was simply extending the super class data with data from
its child

using the id example, Foo.id = 1 is now = [1] and the FooSon does
self.id.append(2)

the system designer wanted inheritance+java and I wanted Python
+Functional Programming
i guess we will meet somewhere in the middle

thanks again
tzury
 
D

Dennis Lee Bieber

I wish it was that simple but 'a = Foo().getid()' is actually creating
a new instance of Foo whereas I want the data of the Foo instanced by
__init__ of FooSon().
And as has been mentioned somewhere in this thread, there is no
"instance" of a Foo... only a FooSon, which is being passed up to the
Foo methods for processing.
what I am actually trying to do is to build a set of classes which
handle different type of binary messages coming from the network.

a base message which handles its basic data parts (src, dst, etc.) and
extending it per message type. thus I looked for a way to get the
child calling super for parsing the super's prats and then having the
child parsing its additional details.

And the safest method for that is probably to make sure that any
attributes of the super that must not be shadowed by the subclasses
begin with double underscores... That way, the Python interpreter name
mangles the attribute to avoid collisions.

Compare your initial attempt:
.... def __init__(self):
.... self.me = "Who am I"
.... print "Super: %s" % id(self)
.... .... def __init__(self):
.... super(Sub, self).__init__()
.... self.me = "Where am I"
.... print "Sub: %s" % id(self)
.... Super: 18485328
Sub: 18485328['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__',
'__hash__', '__init__', '__module__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__',
'me']
Note that both self in both Super and Sub is the same ID, and there
is only one "me"...

vs what you get using __attr in the classes
.... def __init__(self):
.... self.__me = "Who am I"
.... print "Super: %s" % id(self)
.... .... def __init__(self):
.... super(Sub, self).__init__()
.... self.__me = "Where am I"
.... print "Sub: %s" % id(self)
.... Super: 18640080
Sub: 18640080['_Sub__me', '_Super__me', '__class__', '__delattr__', '__dict__',
'__doc__', '__getattribute__', '__hash__', '__init__', '__module__',
'__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
'__str__', '__weakref__']
Now there are _Super_me and _Sub__me, with different values.

--
Wulfraed Dennis Lee Bieber KD6MOG
(e-mail address removed) (e-mail address removed)
HTTP://wlfraed.home.netcom.com/
(Bestiaria Support Staff: (e-mail address removed))
HTTP://www.bestiaria.com/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,772
Messages
2,569,593
Members
45,112
Latest member
VinayKumar Nevatia
Top