[Python-ideas] Fix that broken callable builtin

Christian Heimes christian at python.org
Sat Apr 18 19:43:02 CEST 2015


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

On 2015-04-17 23:39, Guido van Rossum wrote:
> I think you've found an unintended and undocumented backdoor. I
> admit I don't understand how this works in CPython. Overloaded
> operators like __add__ or __call__ should be methods in the class,
> and we don't look for them in the instance. But somehow defining
> them with @property works (I guess because @property is in the
> class).
> 
> What's different for __call__ is that callable() exists. And this
> is probably why I exorcised it Python 3.0 -- but apparently it's
> back. :-(
> 
> In the end callable() doesn't always produce a correct answer; but
> maybe we can make it work in this case by first testing the class
> and then the instance? Something like (untested):
> 
> def callable(x): return hasattr(x.__class__, '__call__') and
> hasattr(x, '__call__')

The code behind callable() is very simple and very fast:

int
PyCallable_Check(PyObject *x)
{
    if (x == NULL)
        return 0;
    return x->ob_type->tp_call != NULL;
}

IMHO the behavior is well in range of the documentation. It also
conforms to my gut feeling and the behavior of PyPy and Jython (tested
with Jython 2.7b3+ and PyPy 2.4.0). The three major Python
implementation agree on callable(o) == hasattr(type(o), '__call__')
for new style classes.

Because PyCallable_Check() is so fast with just two pointer derefs, it
may be used in several hot paths. Any modification may cause a slow
down. This aspect must be thoroughly investigates before the code is
changed.

For all this reasons I'm -1 on the proposed change.

Christian
-----BEGIN PGP SIGNATURE-----

iQEcBAEBCgAGBQJVMpecAAoJEIZoUkkhLbaJyjAH/AiueFdO0wECxZkc53f10Txk
Kjb1RB2SRyNIwcvOR5sXJVCP4OrazlTyDSOeCxQ50I8IBXk2vAbdKVEfjuNW4SqQ
Dr6xijhA2JjAq/TfBHdMJkcGUySBPkBNTn7Dd50TvJm+PE+D4zlGXpgI7rfZXGM5
MwWrphk0/sB6bZ6WSDjdoCQ40V6CZ1uWTU2N5yd/+vtpA91Yl/FB5Xu7x3sRwt0Y
A24GbJHqwgwgnQ7kFozBIbilN3dpcI+Pn5LC6KbqldlNvdp9IMCZh0dm+psnKHVq
2kClbv8f03EahScnKzVh3PblJZ2DB8AEq+PRalmi/v4m0BvWT8a073708BQLocg=
=VJMz
-----END PGP SIGNATURE-----


More information about the Python-ideas mailing list