2012/5/9 Stefan Behnel <stefan...@behnel.de>: > Vitja Makarov, 09.05.2012 10:21: >> 2012/5/9 Stefan Behnel <stefan...@behnel.de>: >>> Vitja Makarov, 09.05.2012 09:43: >>>> 2012/5/9 Stefan Behnel <stefan...@behnel.de>: >>>>> Vitja Makarov, 08.05.2012 13:27: >>>>>> I've noticed regression related to callable() optimization. >>>>>> >>>>>> https://github.com/cython/cython/commit/a40112b0461eae5ab22fbdd07ae798d4a72ff523 >>>>>> >>>>>> class C: >>>>>> pass >>>>>> print callable(C()) >>>>>> >>>>>> It prints True optimized version checks ((obj)->ob_type->tp_call != >>>>>> NULL) condition that is True for both class and instance. >>>>>> >>>>>>>>> help(callable) >>>>>> callable(...) >>>>>> callable(object) -> bool >>>>>> >>>>>> Return whether the object is callable (i.e., some kind of function). >>>>>> Note that classes are callable, as are instances with a __call__() >>>>>> method. >>>>> >>>>> Ah, right - old style classes are special cased in Py2. >>>>> >>>>> I'll make this a Py3-only optimisation then. >>>>> >>>> >>>> I don't see difference between py2 and py3 here: >>>> >>>> Python 3.2.3 (default, May 3 2012, 15:51:42) >>>> [GCC 4.6.3] on linux2 >>>> Type "help", "copyright", "credits" or "license" for more information. >>>>>>> class Foo: pass >>>> ... >>>>>>> callable(Foo()) >>>> False >>>>>>> >>>> >>>> There is PyCallable_Check() CPython function: >>>> >>>> int >>>> PyCallable_Check(PyObject *x) >>>> { >>>> if (x == NULL) >>>> return 0; >>>> if (PyInstance_Check(x)) { >>>> PyObject *call = PyObject_GetAttrString(x, "__call__"); >>>> if (call == NULL) { >>>> PyErr_Clear(); >>>> return 0; >>>> } >>>> /* Could test recursively but don't, for fear of endless >>>> recursion if some joker sets self.__call__ = self */ >>>> Py_DECREF(call); >>>> return 1; >>>> } >>>> else { >>>> return x->ob_type->tp_call != NULL; >>>> } >>>> } >>> >>> That's the Py2 version. In Py3, it looks as follows, because old-style >>> "instances" no longer exist: >>> >>> """ >>> int >>> PyCallable_Check(PyObject *x) >>> { >>> if (x == NULL) >>> return 0; >>> return x->ob_type->tp_call != NULL; >>> } >>> """ >>> >>> That's what I had initially based my optimisation on. >> >> Ok, so why don't you want to use PyCallable_Check() in all cases? > > Well, maybe this isn't performance critical enough to merit inlining. Do > you think it matters? >
Py3k case is quite simple expression so I think it may be inlined. On the other hand it's not often used. -- vitja. _______________________________________________ cython-devel mailing list cython-devel@python.org http://mail.python.org/mailman/listinfo/cython-devel