Class Inheritance - What am I doing wrong?

Discussion in 'Python' started by Brian Munroe, Apr 24, 2008.

  1. Brian Munroe

    Brian Munroe Guest

    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?
     
    Brian Munroe, Apr 24, 2008
    #1
    1. Advertising

  2. On Apr 24, 10:22 pm, 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?


    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...
     
    Virgil Dupras, Apr 24, 2008
    #2
    1. Advertising

  3. Brian Munroe <> 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
     
    Arnaud Delobelle, Apr 24, 2008
    #3
  4. Arnaud Delobelle <> 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
     
    Arnaud Delobelle, Apr 24, 2008
    #4
  5. Brian Munroe

    Gary Herron Guest

    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
     
    Gary Herron, Apr 24, 2008
    #5
  6. Brian Munroe

    Brian Munroe Guest

    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?
     
    Brian Munroe, Apr 24, 2008
    #6
  7. En Thu, 24 Apr 2008 18:18:01 -0300, Brian Munroe
    <> 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
     
    Gabriel Genellina, Apr 25, 2008
    #7
  8. Brian Munroe <> 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
     
    Arnaud Delobelle, Apr 25, 2008
    #8
  9. 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.
     
    Bruno Desthuilliers, Apr 25, 2008
    #9
  10. Brian Munroe

    Brian Munroe Guest

    On Apr 24, 10:11 pm, Arnaud Delobelle <> 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)
     
    Brian Munroe, Apr 25, 2008
    #10
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Salisha Khan
    Replies:
    1
    Views:
    11,696
    JohnFol
    Aug 1, 2003
  2. Keith R. Williams

    What am I doing wrong?

    Keith R. Williams, Jul 14, 2003, in forum: VHDL
    Replies:
    4
    Views:
    1,064
    Ed Diego
    Jul 15, 2003
  3. E11
    Replies:
    1
    Views:
    4,942
    Thomas Weidenfeller
    Oct 12, 2005
  4. johnsonlau
    Replies:
    1
    Views:
    795
    Kai-Uwe Bux
    Jul 21, 2008
  5. Elijah Newren
    Replies:
    1
    Views:
    209
    Peter Otten
    Mar 7, 2009
Loading...

Share This Page