<div dir="ltr"><div class="gmail_extra"><br><div class="gmail_quote">On Sat, Apr 18, 2015 at 1:26 PM, Steven D'Aprano <span dir="ltr"><<a href="mailto:steve@pearwood.info" target="_blank">steve@pearwood.info</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
With new-style classes (but not classic classes), all dunder methods are<br>
only accessed through the class, not the instance. Hence<br>
type(obj).__call__ is correct and obj.__call__ is incorrect.</blockquote></div><br><div class="gmail_default" style="font-family:trebuchet ms,sans-serif">​Yes, this is correct. But unfortunately is also very commonly misunderstood, because even special methods will work through the descriptor protocol. The __new__ method is the only special case here (the infamous "special cased static method").<br><br><blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" class="gmail_quote">py> x.__call__ = lambda self: 23<br></blockquote><div> </div></div><div class="gmail_default" style="font-family:trebuchet ms,sans-serif">The issue never was about patching __call__ on an instance, it's about making  `callable` respect how the method is actually looked up fully (lookup on type + descriptor protocol). What `callable` is missing now is an additional check that will run the descriptor protocol.<br></div><br><div class="gmail_default" style="font-family:trebuchet ms,sans-serif"><blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" class="gmail_quote">​Could this be changed? That deserves a new thread, at least, and<br></blockquote><blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" class="gmail_quote">
possibly a PEP, but briefly:​</blockquote></div><br><div class="gmail_default" style="font-family:trebuchet ms,sans-serif">​So what exactly are you proposing, making a PEP that documents the fact that functions are descriptors and the descriptor protocol is used even for special methods?<br><br></div><div class="gmail_default" style="font-family:trebuchet ms,sans-serif">To give more context here, this is valid and it works right now:<br><br><blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" class="gmail_quote">​>>> class<span style="font-family:monospace,monospace"> NonIter:<br>...     pass<br>...<br>>>> iter(NonIter())<br>Traceback (most recent call last):<br>  File "<stdin>", line 1, in <module><br>TypeError: 'NonIter' object is not iterable<br>>>><br>>>> class DynamicNonIter:<br>...     has_iter = False<br>...<br>...     @property<br>...     def __iter__(self):<br>...         if self.has_iter:<br>...             from functools import partial<br>...             return partial(iter, [1, 2, 3])<br>...         else:<br>...             raise AttributeError("Not really ...")<br>...<br>>>> dni = DynamicNonIter()<br>>>> iter(dni)<br>Traceback (most recent call last):<br>  File "<stdin>", line 1, in <module><br>TypeError: 'DynamicNonIter' object is not iterable<br>>>> dni.has_iter = True<br>>>> iter(dni)<br><list_iterator object at 0x000000000362FF60></span></blockquote></div><br><div class="gmail_default" style="font-family:trebuchet ms,sans-serif">​I don't see why `callable` shouldn't work the same.​</div><br clear="all"><div><div class="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div><div><span style="font-family:trebuchet ms,sans-serif"><span style="color:rgb(51,51,51)"><br><font size="2"><span style="color:rgb(51,51,51)">Thanks,</span><br><span style="color:rgb(153,153,153)">-- Ionel</span></font></span><font size="2"><font style="color:rgb(153,153,153)"> Cristian Mărieș, <a href="http://blog.ionelmc.ro" target="_blank">http://blog.ionelmc.ro</a><br></font></font></span></div></div></div></div></div></div></div>
</div></div>