puzzled about class attribute resolution and mangling

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Brian van den Broek

    #1

    puzzled about class attribute resolution and mangling

    Hi all,

    I've the following code snippet that puzzles me:

    class Base(object):
    __v, u = "Base v", "Base u"
    def __init__(self):
    print self.__v, self.u

    class Derived(Base):
    __v, u = "Derived v", "Derived u"
    def __init__(self):
    print self.__v, self.u
    super(Derived, self).__init__( )

    d = Derived()

    When run (Python 2.4.2, IDLE 1.1.2), it produces:
    [color=blue][color=green][color=darkred]
    >>>[/color][/color][/color]
    Derived v Derived u
    Base v Derived u[color=blue][color=green][color=darkred]
    >>>[/color][/color][/color]

    What I expected was that all four emitted strings would contain "Derived".

    I conclude that there is something about the cluster of concepts at
    hand this hobbyist doesn't understand :-) I suspect that the problem
    is with my understanding of the name mangling mechanism, but then
    again, I'm the confused one.

    I'd thought the point of the mangling was to make it sufficiently
    difficult for client code to access the mangled name so as to
    constitute a strong recommendation to leave the name alone. But, since
    the access is all from within method code, I didn't expect any
    mangling issues here. Since d is a Derived, I expected any method of d
    trying to find d.__v to first check if there is a Derived.__v and only
    then pass to Base.__v. Obviously, that's not what's happening.

    So, is this behaviour entirely by design and my surprise entirely the
    product of misconception or is there an element of side effect of the
    mangling mechanism at issue? Or some other consideration altogether?

    Thanks and best,

    Brian vdB


  • James Stroud

    #2
    Re: puzzled about class attribute resolution and mangling

    Brian van den Broek wrote:[color=blue]
    > Hi all,
    >
    > I've the following code snippet that puzzles me:
    >
    > class Base(object):
    > __v, u = "Base v", "Base u"
    > def __init__(self):
    > print self.__v, self.u
    >
    > class Derived(Base):
    > __v, u = "Derived v", "Derived u"
    > def __init__(self):
    > print self.__v, self.u
    > super(Derived, self).__init__( )
    >
    > d = Derived()
    >
    > When run (Python 2.4.2, IDLE 1.1.2), it produces:
    >[color=green][color=darkred]
    > >>>[/color][/color]
    > Derived v Derived u
    > Base v Derived u[color=green][color=darkred]
    > >>>[/color][/color]
    >
    > What I expected was that all four emitted strings would contain "Derived".
    >
    > I conclude that there is something about the cluster of concepts at
    > hand this hobbyist doesn't understand :-) I suspect that the problem is
    > with my understanding of the name mangling mechanism, but then again,
    > I'm the confused one.
    >
    > I'd thought the point of the mangling was to make it sufficiently
    > difficult for client code to access the mangled name so as to
    > constitute a strong recommendation to leave the name alone. But, since
    > the access is all from within method code, I didn't expect any mangling
    > issues here. Since d is a Derived, I expected any method of d trying to
    > find d.__v to first check if there is a Derived.__v and only then pass
    > to Base.__v. Obviously, that's not what's happening.
    >
    > So, is this behaviour entirely by design and my surprise entirely the
    > product of misconception or is there an element of side effect of the
    > mangling mechanism at issue? Or some other consideration altogether?
    >
    > Thanks and best,
    >
    > Brian vdB
    >
    >[/color]

    This is name mangling at work. Mangling turns self.__v in the Derrived class's
    __init__ method to self._Derrived_ _v and self.__v in the Base class's __init__
    method to self._Base__v. These are different names bound to different values and
    are reflected as such. self.u is the same name in both cases and the value was
    bound in the Derrived class, and not re-bound in the Base class.

    James

    Comment

    • Brian van den Broek

      #3
      Re: puzzled about class attribute resolution and mangling

      James Stroud said unto the world upon 2005-12-09 20:39:[color=blue]
      > Brian van den Broek wrote:
      >[color=green]
      >>Hi all,
      >>
      >>I've the following code snippet that puzzles me:
      >>
      >>class Base(object):
      >> __v, u = "Base v", "Base u"
      >> def __init__(self):
      >> print self.__v, self.u
      >>
      >>class Derived(Base):
      >> __v, u = "Derived v", "Derived u"
      >> def __init__(self):
      >> print self.__v, self.u
      >> super(Derived, self).__init__( )
      >>
      >>d = Derived()
      >>
      >>When run (Python 2.4.2, IDLE 1.1.2), it produces:
      >>[color=darkred]
      >> >>>[/color]
      >>Derived v Derived u
      >>Base v Derived u[color=darkred]
      >> >>>[/color]
      >>
      >>What I expected was that all four emitted strings would contain "Derived".[/color][/color]

      <snip me -- Brian -- speculating on locus of my confusion>
      [color=blue][color=green]
      >>Thanks and best,
      >>
      >>Brian vdB[/color]
      >
      >
      > This is name mangling at work. Mangling turns self.__v in the Derrived class's
      > __init__ method to self._Derrived_ _v and self.__v in the Base class's __init__
      > method to self._Base__v. These are different names bound to different values and
      > are reflected as such. self.u is the same name in both cases and the value was
      > bound in the Derrived class, and not re-bound in the Base class.
      >
      > James[/color]

      Thanks for the reply, James. Rereading the relevant section of the
      Tutorial:
      [color=blue][color=green]
      >> Any identifier of the form __spam (at least two leading
      >> underscores, at most one trailing underscore) is textually replaced
      >> with _classname__spa m, where classname is the current class name
      >> with leading underscore(s) stripped.[/color][/color]
      <http://docs.python.org/tut/node11.html#SEC TION00116000000 00000000000>

      I'm not sure how I came to think that names were mangled only with
      respect to calling code from outside class definitions.

      As I'd been confused, I naturally started thinking of ways to clarify
      the docs. But, I've come to think that the error was wholly mine.

      Thanks for the help,

      Brian vdB


      Comment

      Working...