Accessing 'mangled' class attrbutes

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

    Accessing 'mangled' class attrbutes

    Hello all

    I would like to do the following:

    from elementtree.Sim pleXMLWriter import XMLWriter

    class HtmlWriter(XMLW riter, object):
    def write_raw(self, text):
    super( HtmlWriter, self ).flush()
    super( HtmlWriter, self ).__write(text)

    but because of the name-mangling caused by '__write' I get:

    AttributeError: 'super' object has no attribute '_HtmlWriter__w rite'.

    Is there any simple way round this situation in general?

    (I just want to write out a HTML 'DOCTYPE' declaration)

    Thanks

    Gerard

  • Steve Juranich

    #2
    Re: Accessing 'mangled' class attrbutes

    Gerard Flanagan wrote:
    [color=blue]
    > I would like to do the following:
    >
    > from elementtree.Sim pleXMLWriter import XMLWriter
    >
    > class HtmlWriter(XMLW riter, object):
    > def write_raw(self, text):
    > super( HtmlWriter, self ).flush()
    > super( HtmlWriter, self ).__write(text)
    >
    > but because of the name-mangling caused by '__write' I get:
    >
    > AttributeError: 'super' object has no attribute '_HtmlWriter__w rite'.
    >
    > Is there any simple way round this situation in general?
    >
    > (I just want to write out a HTML 'DOCTYPE' declaration)[/color]

    Try: (not the Python keyword, but a directive to you)

    super(HtmlWrite r, self)._XMLWrite r__write(text)

    In general, to access the name-mangled members, simply add
    _<class_name> to the front of the member name and you should be able to get
    at it. But be careful, since this is a reference to the base class, so if
    it's inherited from some other class, you'll need to know from which class
    the member is inherited.

    HTH

    --
    Steve Juranich
    Tucson, AZ
    USA

    Comment

    • danmcleran@yahoo.com

      #3
      Re: Accessing 'mangled' class attrbutes

      >>Is there any simple way round this situation in general?

      It might be safer to use composition instead of inheritance in this
      case. Assuming that XMLWriter has a write method to write what you
      want, you could hold a reference to an XMLWriter within your class and
      pass along write command like:

      writer = XMLWriter()
      writer.write(st uff)

      Comment

      • Gerard Flanagan

        #4
        Re: Accessing 'mangled' class attrbutes


        Steve Juranich wrote:[color=blue]
        > Gerard Flanagan wrote:
        >[color=green]
        > > I would like to do the following:
        > >
        > > from elementtree.Sim pleXMLWriter import XMLWriter
        > >
        > > class HtmlWriter(XMLW riter, object):
        > > def write_raw(self, text):
        > > super( HtmlWriter, self ).flush()
        > > super( HtmlWriter, self ).__write(text)
        > >
        > > but because of the name-mangling caused by '__write' I get:
        > >
        > > AttributeError: 'super' object has no attribute '_HtmlWriter__w rite'.
        > >
        > > Is there any simple way round this situation in general?
        > >
        > > (I just want to write out a HTML 'DOCTYPE' declaration)[/color]
        >
        > Try: (not the Python keyword, but a directive to you)
        >
        > super(HtmlWrite r, self)._XMLWrite r__write(text)
        >
        > In general, to access the name-mangled members, simply add
        > _<class_name> to the front of the member name and you should be able to get
        > at it. But be careful, since this is a reference to the base class, so if
        > it's inherited from some other class, you'll need to know from which class
        > the member is inherited.
        >
        > HTH
        >
        > --
        > Steve Juranich
        > Tucson, AZ
        > USA[/color]

        I tried that Steve but it didn't work, and i don't think I can do what
        I want in any case. There is no method '__write' in the base class, it
        is only declared as an instance attribute in the constructor, like so:

        def __init__(self, file, encoding="us-ascii"):
        ...
        self.__write = file.write
        ...

        I tried putting '__write = None' at the class level (in the base class
        XMLWriter) but then, although '_XMLWriter__wr ite' appears in
        'dir(HtmlWriter )', I get 'NoneType is not callable'.

        I also tried 'def __write(self, text) : pass ' in the base class, but
        then the code runs but doesn't write the text I want - and anyway, if
        I'm going to change the base class, then i may as well just add the
        'write_raw' method to the base directly!

        It's just some toy code at any rate, and I've learnt something new!
        Thanks for your reply.

        Gerard

        Comment

        • Gerard Flanagan

          #5
          Re: Accessing 'mangled' class attrbutes

          danmcleran@yaho o.com wrote:[color=blue][color=green][color=darkred]
          > >>Is there any simple way round this situation in general?[/color][/color]
          >
          > It might be safer to use composition instead of inheritance in this
          > case. Assuming that XMLWriter has a write method to write what you
          > want, you could hold a reference to an XMLWriter within your class and
          > pass along write command like:
          >
          > writer = XMLWriter()
          > writer.write(st uff)[/color]

          No, XMLWriter doesn't have a 'write' method, if it did I could have
          done:

          super(HtmlWrite r, self).write(stu ff)

          I think the XMLWriter class has been designed so you can't just write
          any old text because this better ensures that tags are properly closed
          and so on. There is a public 'data' method:

          writer.data( text )

          but it escapes angle brackets, and what i wanted was to write
          '<!DOCTYPE..... '.

          Thanks

          Gerard

          Comment

          • Steve Juranich

            #6
            Re: Accessing 'mangled' class attrbutes

            Gerard Flanagan wrote:
            [color=blue]
            > I tried that Steve but it didn't work, and i don't think I can do what
            > I want in any case. There is no method '__write' in the base class, it
            > is only declared as an instance attribute in the constructor, like so:
            >
            > def __init__(self, file, encoding="us-ascii"):
            > ...
            > self.__write = file.write
            > ...
            >
            > I tried putting '__write = None' at the class level (in the base class
            > XMLWriter) but then, although '_XMLWriter__wr ite' appears in
            > 'dir(HtmlWriter )', I get 'NoneType is not callable'.
            >
            > I also tried 'def __write(self, text) : pass ' in the base class, but
            > then the code runs but doesn't write the text I want - and anyway, if
            > I'm going to change the base class, then i may as well just add the
            > 'write_raw' method to the base directly!
            >
            > It's just some toy code at any rate, and I've learnt something new!
            > Thanks for your reply.
            >
            > Gerard
            >[/color]

            Make sure you're calling the super's constructor before you try and access
            the mangled member. Then (I forgot this part), you can just call the
            mangled member from `self'. Example follows.

            <foo.py>
            class A(object):
            def __init__(self):
            self.__foo = lambda x, y : x + y

            class B(A):
            def __init__(self, x, y):
            # Make sure you're calling the super's constructor first.
            super(B, self).__init__( )
            self.sum = self._A__foo(x, y)
            </foo.py>
            [color=blue][color=green][color=darkred]
            >>> import foo
            >>> b = foo.B(3, 4)
            >>> b.sum[/color][/color][/color]
            7[color=blue][color=green][color=darkred]
            >>>[/color][/color][/color]

            --
            Steve Juranich
            Tucson, AZ
            USA

            Comment

            • Gerard Flanagan

              #7
              Re: Accessing 'mangled' class attrbutes

              Steve Juranich wrote:[color=blue]
              > Gerard Flanagan wrote:
              >[color=green]
              > > I tried that Steve but it didn't work, and i don't think I can do what
              > > I want in any case. There is no method '__write' in the base class, it
              > > is only declared as an instance attribute in the constructor, like so:
              > >
              > > def __init__(self, file, encoding="us-ascii"):
              > > ...
              > > self.__write = file.write
              > > ...
              > >
              > > I tried putting '__write = None' at the class level (in the base class
              > > XMLWriter) but then, although '_XMLWriter__wr ite' appears in
              > > 'dir(HtmlWriter )', I get 'NoneType is not callable'.
              > >
              > > I also tried 'def __write(self, text) : pass ' in the base class, but
              > > then the code runs but doesn't write the text I want - and anyway, if
              > > I'm going to change the base class, then i may as well just add the
              > > 'write_raw' method to the base directly!
              > >
              > > It's just some toy code at any rate, and I've learnt something new!
              > > Thanks for your reply.
              > >
              > > Gerard
              > >[/color]
              >
              > Make sure you're calling the super's constructor before you try and access
              > the mangled member. Then (I forgot this part), you can just call the
              > mangled member from `self'. Example follows.
              >
              > <foo.py>
              > class A(object):
              > def __init__(self):
              > self.__foo = lambda x, y : x + y
              >
              > class B(A):
              > def __init__(self, x, y):
              > # Make sure you're calling the super's constructor first.
              > super(B, self).__init__( )
              > self.sum = self._A__foo(x, y)
              > </foo.py>
              >[color=green][color=darkred]
              > >>> import foo
              > >>> b = foo.B(3, 4)
              > >>> b.sum[/color][/color]
              > 7[color=green][color=darkred]
              > >>>[/color][/color]
              >
              > --
              > Steve Juranich
              > Tucson, AZ
              > USA[/color]


              It's all becoming clear! Yes, calling the base constructor was all I
              needed to do:

              class HtmlWriter(elem enttree.SimpleX MLWriter.XMLWri ter, object):

              def __init__(self, file):
              super( HtmlWriter, self).__init__( file)

              def write_raw(self, text):
              self.flush()
              self._XMLWriter __write(text)

              -works a charm. Appreciate your help Steve, thanks again.

              Gerard

              Comment

              Working...