<br><br><div><span class="gmail_quote">On 3/15/07, <b class="gmail_sendername">Greg Ewing</b> &lt;<a href="mailto:greg.ewing@canterbury.ac.nz">greg.ewing@canterbury.ac.nz</a>&gt; wrote:</span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Guido van Rossum wrote:<br>&gt; We could even do this by hacking the default getattr<br>&gt; implementation to skip the instance dict if the name starts and ends<br>&gt; with two underscores.<br><br>But unless I&#39;m mistaken, this behaviour is only
<br>appropriate for *methods*, and you can&#39;t tell<br>just from whether the name has double underscores<br>whether it&#39;s a method or not.</blockquote><div><br>We can make __*__ methods be a different kind of method (by making the metaclass wrap them up in a different kind of descriptor, one with __set__ set. Python treats descriptors with a __set__ slightly different than those without __set__: it bypasses __dict__ entirely, for new-style classes. This trick doesn&#39;t work for classic classes.)
<br><br>For instance:<br><br>import types<br><br>class SpecialMethodDescr(object):<br>&nbsp;&nbsp;&nbsp; def __init__(self, func):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.func = func<br>&nbsp;&nbsp;&nbsp; def __get__(self, inst, cls=None):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # For backward compatibility, insert inst.__dict__ checks and warns here (and we should get our name passed in.)
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return self.func.__get__(inst, cls)<br>&nbsp;&nbsp;&nbsp; def __set__(self, inst, value):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # Possibly allow assignment here, by assigning to inst.__dict__, but warn about it not being used.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; raise AttributeError
<br><br>class SMDType(type):<br>&nbsp;&nbsp;&nbsp; def __new__(cls, name, bases, attrs):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for attr in attrs:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (attr.startswith(&quot;__&quot;) and attr.endswith(&quot;__&quot;) and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; isinstance(attrs[attr], 
types.FunctionType)):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; attrs[attr] = SpecialMethodDescr(attrs[attr])<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return super(SMDType, cls).__new__(cls, name, bases, attrs)<br><br>class smd_object(object):<br>&nbsp;&nbsp;&nbsp; __metaclass__ = SMDType
<br><br>And to see it in action:<br><br>&gt;&gt;&gt; class Old(object):<br>...&nbsp;&nbsp; def __repr__(self):<br>...&nbsp;&nbsp;&nbsp;&nbsp; return &quot;Old.__repr__&quot;<br>...<br>&gt;&gt;&gt; class New(smd_object):<br>...&nbsp;&nbsp; def __repr__(self):<br>
...&nbsp;&nbsp;&nbsp;&nbsp; return &quot;New.__repr__&quot;<br>...<br>&gt;&gt;&gt; o = Old()<br>&gt;&gt;&gt; n = New()<br>&gt;&gt;&gt; def o_repr():<br>...&nbsp;&nbsp; return &quot;o_repr&quot;<br>...<br>&gt;&gt;&gt; o.__dict__[&#39;__repr__&#39;] = o_repr
<br>&gt;&gt;&gt; def n_repr():<br>...&nbsp;&nbsp; return &quot;n_repr&quot;<br>...<br>&gt;&gt;&gt; n.__dict__[&#39;__repr__&#39;] = n_repr<br>&gt;&gt;&gt; o<br>Old.__repr__<br>&gt;&gt;&gt; n<br>New.__repr__<br>&gt;&gt;&gt; o.__repr__()
<br>&#39;o_repr&#39;<br>&gt;&gt;&gt; n.__repr__()<br>&#39;New.__repr__&#39;<br><br></div></div>-- <br>Thomas Wouters &lt;<a href="mailto:thomas@python.org">thomas@python.org</a>&gt;<br><br>Hi! I&#39;m a .signature virus! copy me into your .signature file to help me spread!