inheritance and private attributes

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • KN

    inheritance and private attributes


    I've run into such problem:

    I have something like this:

    class A(object):
    def __init__(self):
    self.__value = None

    class B(A):
    def test(self):
    if self.__value:
    print "Ok."
    else:
    print "Empty."
    [color=blue][color=green][color=darkred]
    >>> b = B()
    >>> b.test()[/color][/color][/color]
    Traceback (most recent call last):
    File "<stdin>", line 1, in ?
    File "<stdin>", line 3, in test
    AttributeError: 'B' object has no attribute '_B__value'

    Why I have no access to private attribute from a class that
    inherits other class? I just want to have access to the same
    private variables but also to extend its functionality by
    adding a method that operates on those private attributes and
    I'm unable to do so.

    Is this normal behaviour? What should I do if I want to
    override method and use private attribute, or just add
    some other method which changes this attribute?

    /K

  • Peter Otten

    #2
    Re: inheritance and private attributes

    KN wrote:
    [color=blue]
    >
    > I've run into such problem:
    >
    > I have something like this:
    >
    > class A(object):
    > def __init__(self):
    > self.__value = None
    >
    > class B(A):
    > def test(self):
    > if self.__value:[/color]

    change the above to
    if self._A__value:
    [color=blue]
    > print "Ok."
    > else:
    > print "Empty."
    >[color=green][color=darkred]
    >>>> b = B()
    >>>> b.test()[/color][/color]
    > Traceback (most recent call last):
    > File "<stdin>", line 1, in ?
    > File "<stdin>", line 3, in test
    > AttributeError: 'B' object has no attribute '_B__value'
    >
    > Why I have no access to private attribute from a class that
    > inherits other class? I just want to have access to the same
    > private variables but also to extend its functionality by
    > adding a method that operates on those private attributes and
    > I'm unable to do so.
    >
    > Is this normal behaviour? What should I do if I want to
    > override method and use private attribute, or just add
    > some other method which changes this attribute?[/color]

    Python performs name mangling for attributes starting with two underscores.
    This is meant to avoid accidental nameclashes of attributes that are rather
    an implementation detail than of interest to subclasses and the wider
    public. I like many others use attribute names with a *single* leading
    underscore (i. e. no name mangling) to signal "this is may change without
    prior notice" while omitting artificial hurdles.
    This is also known as treating programmers as adults :-)

    Peter


    Comment

    • A. Lloyd Flanagan

      #3
      Re: inheritance and private attributes

      KN <vald@dead.art. pl> wrote in message news:<mailman.8 74.1082573632.2 0120.python-list@python.org >...[color=blue]
      > I've run into such problem:
      >
      > I have something like this:
      >
      > class A(object):
      > def __init__(self):
      > self.__value = None
      >
      > class B(A):
      > def test(self):
      > if self.__value:
      > print "Ok."
      > else:
      > print "Empty."
      >[color=green][color=darkred]
      > >>> b = B()
      > >>> b.test()[/color][/color]
      > Traceback (most recent call last):
      > File "<stdin>", line 1, in ?
      > File "<stdin>", line 3, in test
      > AttributeError: 'B' object has no attribute '_B__value'
      >
      > Why I have no access to private attribute from a class that
      > inherits other class? I just want to have access to the same
      > private variables but also to extend its functionality by
      > adding a method that operates on those private attributes and
      > I'm unable to do so.
      >
      > Is this normal behaviour? What should I do if I want to
      > override method and use private attribute, or just add
      > some other method which changes this attribute?
      >
      > /K[/color]

      This is normal behavior (by design). In general a derived class has
      no special access to the attributes defined in its parent; there is no
      equivalent of C++'s "protected" variables.

      I see two solutions:

      1) Have the child use an accessor function (if class A above had a
      getValue() method, you could call it with A.getValue(self )).

      2) Cheat. In class B, access self._A__value. This duplicates the
      "mangling" that python does to hide variables with double underscore
      in front.

      I'd recommend 1), unless you have some urgent performance problem. 2)
      is probably a bit faster.

      Fast example of 2):[color=blue][color=green][color=darkred]
      >>> class a:[/color][/color][/color]
      .... def __init__(self):
      .... a.val = 3
      .... def getValue(self):
      .... return a.__val
      .... def __init__(self):
      .... a.__val = 3[color=blue][color=green][color=darkred]
      >>> x = a()
      >>> a.getValue()[/color][/color][/color]
      3[color=blue][color=green][color=darkred]
      >>> class b(a):[/color][/color][/color]
      .... def __init__(self):
      .... a.__init__(self )
      .... def getValue(self):
      .... return a._a__val + 2
      ....[color=blue][color=green][color=darkred]
      >>> y = b()
      >>> y.getValue()[/color][/color][/color]
      5

      Comment

      Working...