<p>Below I have a very simple example of what I'm trying to do.  I want to be able to use HTMLDecorator with any other class.  Ignore the fact it's called decorator, it's just a name.</p>

<pre><code>import cgi

class ClassX(object):
  pass # ... with own __repr__

class ClassY(object):
  pass # ... with own __repr__

inst_x=ClassX()

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(("&lt;H1&gt;","&lt;/H1&gt;"))

print HTMLDecorator(inst_x).html()
print HTMLDecorator(inst_y).html()
wrapped_z = HTMLDecorator(inst_z)
inst_z[0] += 70
wrapped_z[0] += 71
print wrapped_z.html()
print HTMLDecorator(inst_b).html()
</code></pre>

<p>Output:</p>

<pre>Traceback (most recent call last):
  File "html.py", line 21, in 
    print HTMLDecorator(inst_x).html()
TypeError: default __new__ takes no parameters</pre>

<p>Is what I'm trying to do possible?  If so, what am I doing wrong?</p>

[{'answer_id': 37488, 'author': 'John Millikin', 'author_id': 3560, 'author_profile': 'https://Stackoverflow.com/users/3560', 'pm_score': 0, 'selected': False, 'text': '<blockquote>\n  <p>Is what I\'m trying to do possible? If so, what am I doing wrong?</p>\n</blockquote>\n\n<p>It\'s certainly possible. What\'s wrong is that <code>HTMLDecorator.__init__()</code> doesn\'t accept parameters.</p>\n\n<p>Here\'s a simple example:</p>\n\n<pre><code>def decorator (func):\n    def new_func ():\n        return "new_func %s" % func ()\n    return new_func\n\n@decorator\ndef a ():\n    return "a"\n\ndef b ():\n    return "b"\n\nprint a() # new_func a\nprint decorator (b)() # new_func b\n</code></pre>\n'}, {'answer_id': 37513, 'author': 'Harley Holcombe', 'author_id': 1057, 'author_profile': 'https://Stackoverflow.com/users/1057', 'pm_score': 0, 'selected': False, 'text': "<p>@John (37448):</p>\n\n<p>Sorry, I might have misled you with the name (bad choice).  I'm not really looking for a decorator function, or anything to do with decorators at all.  What I'm after is for the html(self) def to use ClassX or ClassY's <code>__repr__</code>.  I want this to work without modifying ClassX or ClassY.</p>\n"}, {'answer_id': 37526, 'author': 'John Millikin', 'author_id': 3560, 'author_profile': 'https://Stackoverflow.com/users/3560', 'pm_score': 0, 'selected': False, 'text': '<p>Ah, in that case, perhaps code like this will be useful? It doesn\'t really have anything to do with decorators, but demonstrates how to pass arguments to a class\'s initialization function and to retrieve those arguments for later.</p>\n\n<pre><code>import cgi\n\nclass ClassX(object):\n    def __repr__ (self):\n        return "&lt;class X&gt;"\n\nclass HTMLDecorator(object):\n    def __init__ (self, wrapped):\n        self.__wrapped = wrapped\n\n    def html (self):\n        sep = cgi.escape (repr (self.__wrapped))\n        return sep.join (("&lt;H1&gt;", "&lt;/H1&gt;"))\n\ninst_x=ClassX()\ninst_b=True\n\nprint HTMLDecorator(inst_x).html()\nprint HTMLDecorator(inst_b).html()\n</code></pre>\n'}, {'answer_id': 37544, 'author': 'Harley Holcombe', 'author_id': 1057, 'author_profile': 'https://Stackoverflow.com/users/1057', 'pm_score': 0, 'selected': False, 'text': '<p>@John (37479):</p>\n\n<p>Very close, but then I lose everything from ClassX.  Below is something a collegue gave me that does do the trick, but it\'s hideous.  There has to be a better way.</p>\n\n<pre><code>import cgi\nfrom math import sqrt\n\nclass ClassX(object): \n  def __repr__(self): \n    return "Best Guess"\n\nclass ClassY(object):\n  pass # ... with own __repr__\n\ninst_x=ClassX()\n\ninst_y=ClassY()\n\ninst_z=[ i*i for i in range(25) ]\n\ninst_b=True\n\navoid="__class__ __init__ __dict__ __weakref__"\n\nclass HTMLDecorator(object):\n    def __init__(self,master):\n        self.master = master\n        for attr in dir(self.master):\n            if ( not attr.startswith("__") or \n                attr not in avoid.split() and "attr" not in attr):\n                self.__setattr__(attr, self.master.__getattribute__(attr))\n\n    def html(self): # an "enhanced" version of __repr__\n        return cgi.escape(self.__repr__()).join(("&lt;H1&gt;","&lt;/H1&gt;"))\n\n    def length(self):\n        return sqrt(sum(self.__iter__()))\n\nprint HTMLDecorator(inst_x).html()\nprint HTMLDecorator(inst_y).html()\nwrapped_z = HTMLDecorator(inst_z)\nprint wrapped_z.length()\ninst_z[0] += 70\n#wrapped_z[0] += 71\nwrapped_z.__setitem__(0,wrapped_z.__getitem__(0)+ 71)\nprint wrapped_z.html()\nprint HTMLDecorator(inst_b).html()\n</code></pre>\n\n<p>Output:</p>\n\n<pre>&lt;H1&gt;Best Guess&lt;/H1&gt;\n&lt;H1&gt;&lt;__main__.ClassY object at 0x891df0c&gt;&lt;/H1&gt;\n70.0\n&lt;H1&gt;[141, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400, 441, 484, 529, 576]&lt;/H1&gt;\n&lt;H1&gt;True&lt;/H1&gt;</pre>\n'}, {'answer_id': 37571, 'author': 'John Millikin', 'author_id': 3560, 'author_profile': 'https://Stackoverflow.com/users/3560', 'pm_score': 3, 'selected': True, 'text': '<blockquote>\n  <p>Very close, but then I lose everything from ClassX. Below is something a collegue gave me that does do the trick, but it\'s hideous. There has to be a better way.</p>\n</blockquote>\n\n<p>Looks like you\'re trying to set up some sort of proxy object scheme. That\'s doable, and there are better solutions than your colleague\'s, but first consider whether it would be easier to just patch in some extra methods. This won\'t work for built-in classes like <code>bool</code>, but it will for your user-defined classes:</p>\n\n<pre><code>def HTMLDecorator (obj):\n    def html ():\n        sep = cgi.escape (repr (obj))\n        return sep.join (("&lt;H1&gt;", "&lt;/H1&gt;"))\n    obj.html = html\n    return obj\n</code></pre>\n\n<p>And here is the proxy version:</p>\n\n<pre><code>class HTMLDecorator(object):\n    def __init__ (self, wrapped):\n        self.__wrapped = wrapped\n\n    def html (self):\n        sep = cgi.escape (repr (self.__wrapped))\n        return sep.join (("&lt;H1&gt;", "&lt;/H1&gt;"))\n\n    def __getattr__ (self, name):\n        return getattr (self.__wrapped, name)\n\n    def __setattr__ (self, name, value):\n        if not name.startswith (\'_HTMLDecorator__\'):\n            setattr (self.__wrapped, name, value)\n            return\n        super (HTMLDecorator, self).__setattr__ (name, value)\n\n    def __delattr__ (self, name):\n        delattr (self.__wraped, name)\n</code></pre>\n'}, {'answer_id': 37619, 'author': 'Carl Meyer', 'author_id': 3207, 'author_profile': 'https://Stackoverflow.com/users/3207', 'pm_score': 2, 'selected': False, 'text': '<p>Both of John\'s solutions would work.  Another option that allows HTMLDecorator to remain very simple and clean is to monkey-patch it in as a base class.  This also works only for user-defined classes, not builtin types:</p>\n\n<pre><code>import cgi\n\nclass ClassX(object):\n    pass # ... with own __repr__\n\nclass ClassY(object):\n    pass # ... with own __repr__\n\ninst_x=ClassX()\ninst_y=ClassY()\n\nclass HTMLDecorator:\n    def html(self): # an "enhanced" version of __repr__\n        return cgi.escape(self.__repr__()).join(("&lt;H1&gt;","&lt;/H1&gt;"))\n\nClassX.__bases__ += (HTMLDecorator,)\nClassY.__bases__ += (HTMLDecorator,)\n\nprint inst_x.html()\nprint inst_y.html()\n</code></pre>\n\n<p>Be warned, though -- monkey-patching like this comes with a high price in readability and maintainability of your code.  When you go back to this code a year later, it can become very difficult to figure out how your ClassX got that html() method, especially if ClassX is defined in some other library.</p>\n'}]
['https://Stackoverflow.com/questions/37479', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/1057/']