Accessing 'mangled' class attrbutes

  • Thread starter Gerard Flanagan
  • Start date
G

Gerard Flanagan

Hello all

I would like to do the following:

from elementtree.SimpleXMLWriter import XMLWriter

class HtmlWriter(XMLWriter, 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__write'.

Is there any simple way round this situation in general?

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

Thanks

Gerard
 
S

Steve Juranich

Gerard said:
I would like to do the following:

from elementtree.SimpleXMLWriter import XMLWriter

class HtmlWriter(XMLWriter, 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__write'.

Is there any simple way round this situation in general?

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

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

super(HtmlWriter, self)._XMLWriter__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
 
D

danmcleran

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(stuff)
 
G

Gerard Flanagan

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

super(HtmlWriter, self)._XMLWriter__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

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__write' 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
 
G

Gerard Flanagan

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(stuff)

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

super(HtmlWriter, self).write(stuff)

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
 
S

Steve Juranich

Gerard said:
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__write' 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

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)
 
G

Gerard Flanagan

Steve said:
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)


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

class HtmlWriter(elementtree.SimpleXMLWriter.XMLWriter, 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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top