Neville Dempsey a écrit :
What do I need to add to HTMLDecorator?
A simpler example:
import cgi
class ClassX(object):
pass # ... with own __repr__
class ClassY(object):
pass # ... with own __repr__
inst_x=ClassX()
Why do you need to prefix your variables with 'inst_' ?
inst_y=ClassY()
inst_z=[ i*i for i in range(25) ]
inst_b=True
class HTMLDecorator(object):
def html(self): # an "enhanced" version of __repr__
return cgi.escape(self.__repr__()).join(("<H1>","</H1>"))
<ot>
uppercase tags are so 1990...
</ot>
More seriously, your code would be more readable (and more maintainable)
using string formatting, ie:
def html(self): # an "enhanced" version of __repr__
return cgi.escape("<h1>%r</h1>" % self)
print HTMLDecorator(inst_x).html()
(snip unexecuted code)
Output:
Traceback (most recent call last):
File "html.py", line 21, in <module>
print HTMLDecorator(inst_x).html()
TypeError: default __new__ takes no parameters
Can I simply decorate an existing instance?
For which definitions of "simply" and "decorate", and for instances of
what ?
Some classes will let you add arbitrary attributes to either themselves
of their instances. Some (hint: mostly builtin types) wont, because
they've been implemented otherwise, usually for performances reasons.
If all you need is a simple enhanced "html" __repr__, just use a generic
function - being OO doesn't mean you have to use classes everywhere
(hint : OO stands for "object oriented", not "class oriented"). All you
need here is:
def html(obj, tag="h1"):
return "<%s>%s</%s>" % (tag, cgi.escape(repr(obj)), tag)
If you have more responsabilities to add, and want something generic,
then you'll have to use composition/delegation instead of inheritance, ie:
class HTMLDecorator(object):
def __init__(self, obj):
# use name mangling to avoid possible name clash
self.__obj = obj
def html(self):
# reuse the above generic html() func
return html(self.__obj)
def __getattr__(self, name):
# trivial, always delegate - __getattr__ is
# only called when evrything else failed
return getattr(self.__obj, name)
def __setattr__(self, name, value):
# tricky : __setattr__ is *always* called
if name == "_HTMLDecorator__obj" or name in type(self).__dict__:
super(HTMLDecorator, self).__setattr__(name, value)
else:
setattr(self.__obj, name, value)
But be warned that this might be tricky (I wouldn't bet a truly generic
implementation of the class decorator pattern is something doable), and
that you'll have to pay the price (wrt/ perfs) for overriding
__setattr__. As a general rule, it's better to avoid overridding
__getattribute__ and __setattr__ whenever possible.
HTH
--
http://mail.python.org/mailman/listinfo/python-list