[Python-ideas] Fix that broken callable builtin
Steven D'Aprano
steve at pearwood.info
Sat Apr 18 12:26:34 CEST 2015
On Fri, Apr 17, 2015 at 02:10:30PM -0700, Ethan Furman wrote:
> On 04/18, Ionel Cristian Mărieș wrote:
>
> > Also there's the issue about not being able to implement a true proxy (as
> > outlined before).
>
> Proxies are a bit of a pain. But you can create your own callable function.
>
> Something like (untested):
>
> def callable(obj):
> try:
> func = obj.__call__
> return True
> except AttributeError:
> return False
You can define it like that, but it doesn't work.
Using the above definition of callable:
py> class Spam(object):
... pass
...
py> x = Spam()
py> x.__call__ = lambda self: 23
py> callable(x)
True
py> x()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'Spam' object is not callable
"foo()" syntax does not look for a __call__ method on the instance, only
on the type. The current behaviour of callable is correct:
py> builtins.callable(x)
False
With new-style classes (but not classic classes), all dunder methods are
only accessed through the class, not the instance. Hence
type(obj).__call__ is correct and obj.__call__ is incorrect.
Could this be changed? That deserves a new thread, at least, and
possibly a PEP, but briefly:
(1) The current behaviour is documented, so it would require some form
of transition;
(2) The current behaviour is intended as an optimization. Using Python
2.7 on my system, I find that a minimal __add__ method is more than
three times faster using a new-style class compared to a classic class.
--
Steve
More information about the Python-ideas
mailing list