-----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-----