Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Class Inheritance - What am I doing wrong?

Reply
Thread Tools

Class Inheritance - What am I doing wrong?

 
 
Brian Munroe
Guest
Posts: n/a
 
      04-24-2008
My example:

class A(object):

def __init__(self, name):
self.__name = name

def getName(self):
return self.__name

class B(A):

def __init__(self,name=None):
super(A,self).__init__()

def setName(self, name):
self.__name = name

if __name__ == '__main__':

a = A('class a')
print a.getName()

b = B('class b')
print b.getName()

b.setName('class b, reset')
print b.getName()

I get the following error:

mtinky:~ brian$ python teste.py
class a
Traceback (most recent call last):
File "teste.py", line 23, in <module>
print b.getName()
File "teste.py", line 7, in getName
return self.__name
AttributeError: 'B' object has no attribute '_A__name'

Am I *not* using super() correctly? Also, did I define my the class B
constructor correctly?
 
Reply With Quote
 
 
 
 
Virgil Dupras
Guest
Posts: n/a
 
      04-24-2008
On Apr 24, 10:22*pm, Brian Munroe <(E-Mail Removed)> wrote:
> My example:
>
> class A(object):
>
> * * * * def __init__(self, name):
> * * * * * * * * self.__name = name
>
> * * * * def getName(self):
> * * * * * * * * return self.__name
>
> class B(A):
>
> * * * * def __init__(self,name=None):
> * * * * * * * * super(A,self).__init__()
>
> * * * * def setName(self, name):
> * * * * * * * * self.__name = name
>
> if __name__ == '__main__':
>
> * * * * a = A('class a')
> * * * * print a.getName()
>
> * * * * b = B('class b')
> * * * * print b.getName()
>
> * * * * b.setName('class b, reset')
> * * * * print b.getName()
>
> I get the following error:
>
> mtinky:~ brian$ python teste.py
> class a
> Traceback (most recent call last):
> * File "teste.py", line 23, in <module>
> * * print b.getName()
> * File "teste.py", line 7, in getName
> * * return self.__name
> AttributeError: 'B' object has no attribute '_A__name'
>
> Am I *not* using super() correctly? *Also, did I define my the class B
> constructor correctly?


Exactly, you used it wrong. It's super(B, self).

But before you start using super() everywhere, read this:

http://fuhm.net/super-harmful/

I love Python, but super() is one of those tricky things...
 
Reply With Quote
 
 
 
 
Arnaud Delobelle
Guest
Posts: n/a
 
      04-24-2008
Brian Munroe <(E-Mail Removed)> writes:

> My example:
>
> class A(object):
>
> def __init__(self, name):
> self.__name = name
>
> def getName(self):
> return self.__name
>
> class B(A):
>
> def __init__(self,name=None):
> super(A,self).__init__()
>
> def setName(self, name):
> self.__name = name
>
> if __name__ == '__main__':
>
> a = A('class a')
> print a.getName()
>
> b = B('class b')
> print b.getName()
>
> b.setName('class b, reset')
> print b.getName()
>
> I get the following error:
>
> mtinky:~ brian$ python teste.py
> class a
> Traceback (most recent call last):
> File "teste.py", line 23, in <module>
> print b.getName()
> File "teste.py", line 7, in getName
> return self.__name
> AttributeError: 'B' object has no attribute '_A__name'
>
> Am I *not* using super() correctly? Also, did I define my the class B
> constructor correctly?


You have fallen victim to the Name Mangling Trap [1]. Replace the
leading double underscore in the __name attribute with a single one,
and Python shall calm down and let your code behave as you expect it
to.

That is, if you also pass the name parameter to super(A,self).__init__
in B's __init__ method

[1] http://docs.python.org/ref/atom-identifiers.html

--
Arnaud
 
Reply With Quote
 
Arnaud Delobelle
Guest
Posts: n/a
 
      04-24-2008
Arnaud Delobelle <(E-Mail Removed)> writes:

> That is, if you also pass the name parameter to super(A,self).__init__
> in B's __init__ method


Oops. should be super(B, self).__init__(name), of course.

--
Arnaud
 
Reply With Quote
 
Gary Herron
Guest
Posts: n/a
 
      04-24-2008
Brian Munroe wrote:
> My example:
>
> class A(object):
>
> def __init__(self, name):
> self.__name = name
>
> def getName(self):
> return self.__name
>
> class B(A):
>
> def __init__(self,name=None):
> super(A,self).__init__()
>
> def setName(self, name):
> self.__name = name
>
> if __name__ == '__main__':
>
> a = A('class a')
> print a.getName()
>
> b = B('class b')
> print b.getName()
>
> b.setName('class b, reset')
> print b.getName()
>
> I get the following error:
>
> mtinky:~ brian$ python teste.py
> class a
> Traceback (most recent call last):
> File "teste.py", line 23, in <module>
> print b.getName()
> File "teste.py", line 7, in getName
> return self.__name
> AttributeError: 'B' object has no attribute '_A__name'
>
> Am I *not* using super() correctly? Also, did I define my the class B
> constructor correctly?
> --
> http://mail.python.org/mailman/listinfo/python-list
>


Tell us what you are trying to do and what you expected to happen.

If you are trying to do simple inheritance, you don't need the supers,
and you should not invoke the name mangling implied by the double
underscore.

If you *are* trying to use the name mangling, then you still don't need
the super.


Gary Herron


 
Reply With Quote
 
Brian Munroe
Guest
Posts: n/a
 
      04-24-2008
Ok, so thanks everyone for the helpful hints. That *was* a typo on my
part (should've been super(B...) not super(A..), but I digress)

I'm building a public API. Along with the API I have a few custom
types that I'm expecting API users to extend, if they need too. If I
don't use name mangling, isn't that considered bad practice (read not
defensive programming) to not protect those 'private' fields?
 
Reply With Quote
 
Gabriel Genellina
Guest
Posts: n/a
 
      04-25-2008
En Thu, 24 Apr 2008 18:18:01 -0300, Brian Munroe
<(E-Mail Removed)> escribió:

> Ok, so thanks everyone for the helpful hints. That *was* a typo on my
> part (should've been super(B...) not super(A..), but I digress)
>
> I'm building a public API. Along with the API I have a few custom
> types that I'm expecting API users to extend, if they need too. If I
> don't use name mangling, isn't that considered bad practice (read not
> defensive programming) to not protect those 'private' fields?


Please read this article:
<http://dirtsimple.org/2004/12/python-is-not-java.html>
You don't have to define any getXXX/setXXX methods, just use a public
attribute (if it is supposed to be public, of course). In case you have to
do something special with it (like notifying some observers when the value
changes, by example) use a property instead, and use a *single* leading
underscore in the protected attribute name. In any case, the client code
remains the same: some_object.attribute_name = value

In Python, a single leading underscore means "this is an implementation
detail, don't mess with it". This is a convention and we all -adult and
responsible programmers- follow that convention. Double leading
underscores are a means to avoid name conflicts with subclasses - don't
use them unless you have a valid reason. Double leading and trailing
underscores are __special__ names reserved by Python itself.

--
Gabriel Genellina

 
Reply With Quote
 
Arnaud Delobelle
Guest
Posts: n/a
 
      04-25-2008
Brian Munroe <(E-Mail Removed)> writes:

> Ok, so thanks everyone for the helpful hints. That *was* a typo on my
> part (should've been super(B...) not super(A..), but I digress)
>
> I'm building a public API. Along with the API I have a few custom
> types that I'm expecting API users to extend, if they need too. If I
> don't use name mangling, isn't that considered bad practice (read not
> defensive programming) to not protect those 'private' fields?


The problem is that you are using name mangling for an attribute which
is accessed by several generations of a class hierarchy. Name
mangling is only useful for attributes you *don't* want to share with
subclasses (or bases).

In python, use attributes starting with a single underscore (such as
_name). It tells users that they shouldn't mess with them. By
design, python doesn't include mechanisms equivalent to the Java / C++
'private'.

--
Arnaud
 
Reply With Quote
 
Bruno Desthuilliers
Guest
Posts: n/a
 
      04-25-2008
Brian Munroe a écrit :
> Ok, so thanks everyone for the helpful hints. That *was* a typo on my
> part (should've been super(B...) not super(A..), but I digress)
>
> I'm building a public API. Along with the API I have a few custom
> types that I'm expecting API users to extend, if they need too. If I
> don't use name mangling, isn't that considered bad practice (read not
> defensive programming) to not protect those 'private' fields?


There would be a lot to say about whether defensive programming is a
good practice or not. At least in the context of hi-level languages with
exception handling and automatic memory management.

Anyway:
- there's just no way to make anything truly "private" in Python
- the convention is that attributes (including methods - they are
attributes too) whose name starts with a single leading underscore are
implementation stuff and should not be messed with. IOW, the contract is
"mess with them and you're on your own".
- name mangling is only useful when you really need to make sure an
implementation attribute won't be *accidentally* shadowed. These
attributes should only be used by methods that are not themselves
supposed to be overridden or extended by user code. FWIW, I must have
used them less than half a dozen times in 7+ years (and I wrote more
than a couple mini-frameworks, with lot of black-juju metaclasses and
custom descriptors magic in them).

So just use single-leading-underscore for implementation attributes, and
document what the users are supposed to extend and what they're supposed
to leave alone.

My 2 cents.
 
Reply With Quote
 
Brian Munroe
Guest
Posts: n/a
 
      04-25-2008
On Apr 24, 10:11 pm, Arnaud Delobelle <(E-Mail Removed)> wrote:

> In python, use attributes starting with a single underscore (such as
> _name). It tells users that they shouldn't mess with them. By
> design, python doesn't include mechanisms equivalent to the Java / C++
> 'private'.


Arnaud, Gabriel:

Ok, Ok, I'll trust my users to not abuse my API I didn't realize
that 'private' meant 'private, even to sub-classes' - it is all
becoming clear to me now!

Thanks for the help, and I'm going to re-read 'Python is Not Java'
right about now (I've spent the past few months knee-deep in Java, I
guess I need to cleanse myself)
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Import, Inheritance, Scoping -- I'm doing something wrong with one ofthese Elijah Newren Python 1 03-07-2009 05:23 PM
C++ Struct inheritance against class inheritance johnsonlau C++ 1 07-21-2008 04:58 PM
Nested Class, Member Class, Inner Class, Local Class, Anonymous Class E11 Java 1 10-12-2005 03:34 PM
mul. inheritance & overloading operator new/delete solved by virtual base inheritance? cppsks C++ 0 10-27-2004 07:49 PM
Private access modifier and Inheritance (Inheritance implementation in Java) maxw_cc Java 1 12-21-2003 11:38 AM



Advertisments