<div dir="ltr"><div class="gmail_default" style="font-family:trebuchet ms,sans-serif">Hello,<br><br></div><div class="gmail_default" style="font-family:trebuchet ms,sans-serif">I had an issue today with the `callable` builtin because it doesn't correctly check that the object has the __call__ attribute. <br><br></div><div class="gmail_default" style="font-family:trebuchet ms,sans-serif">Effectively what `callable(a)` does is `hasattr(type(a), '__call__')` but that's not very straightforward. A more straightforward implementation would do something like `hasattr(a, '__call__')`.<br><br></div><div class="gmail_default" style="font-family:trebuchet ms,sans-serif">For example:<br><br><blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" class="gmail_quote">Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:44:40) [MSC v.1600 64 bit (AMD64)] on win32<br>Type "help", "copyright", "credits" or "license" for more information.<br>>>> callable<br><built-in function callable><br>>>> class A:<br>... @property<br>... def __call__(self):<br>... raise AttributeError('go away')<br>...<br>>>> a = A()<br>>>> a<br><__main__.A object at 0x000000000365B5C0><br>>>> a.__call__<br>Traceback (most recent call last):<br> File "<stdin>", line 1, in <module><br> File "<stdin>", line 4, in __call__<br>AttributeError: go away<br>>>> callable(a)<br>True<br>>>> # it should be False :(<br></blockquote></div><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><div class="gmail_default" style="font-family:trebuchet ms,sans-serif;display:inline">So it boils down to this:<br><blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" class="gmail_quote">>>> hasattr(a, "__call__")<br>False<br>>>> hasattr(type(a), "__call__")<br>True</blockquote><div><br></div><div>My issue is that I didn't call `callable(type(a))` but just `callable(a)`. Clearly mismatching what happens when you do hasattr(a, "__call__").<br><br></div><div>To put in contrast, this is legal and clearly indicates the descriptors are being used as expected:<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 B:<br>... @property<br>... def __call__(self):<br>... return lambda: 1<br>...<br>>>> b = B()<br>>>> b()<br>1<br></blockquote></div></div></span></span><span style="font-family:trebuchet ms,sans-serif"><span style="color:rgb(51,51,51)"><br><div class="gmail_default" style="font-family:trebuchet ms,sans-serif;display:inline">There</div><div class="gmail_default" style="font-family:trebuchet ms,sans-serif;display:inline">'s some more discussing in <a href="http://bugs.python.org/issue23990">issue <span style="font-family:trebuchet ms,sans-serif"><span style="color:rgb(51,51,51)">23990</span></span></a></div><div class="gmail_default" style="font-family:trebuchet ms,sans-serif;display:inline"> where I get slightly angry, sorry.</div><br><br><div class="gmail_default" style="font-family:trebuchet ms,sans-serif;display:inline">So were is this change actually useful? Proxies! Since new-style objects in Python you cannot really proxy the callable aspect of objects, because `callable` just checks that a field is set in a C struct.</div><div class="gmail_default" style="font-family:trebuchet ms,sans-serif;display:inline"> This is fairly inconvenient because you have to know upfront if your target is going to be callable or not.</div><br><br><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>