On Sat, Apr 18, 2015 at 02:41:29PM +0300, Ionel Cristian Mărieș wrote:
On Sat, Apr 18, 2015 at 2:23 PM, Steven D'Aprano <steve@pearwood.info> wrote:
Are you sure this doesn't already work? It works for me in Python 3.3:
It doesn't really work because of the incomplete checks done in `callable_builtin`. This is what I've tried:
class DynamicCallable: ... is_callable = True ... ... def __init__(self, target): ... self.target = target ... ... @property ... def __call__(self): ... if self.is_callable: ... return self.target ... else: ... raise AttributeError("Not really ...") ...
dc = DynamicCallable(print) dc(1, 2, 3) 1 2 3 callable(dc) True dc.is_callable = False callable(dc) True ###### This should be False :(
Why do you think that it should be false? If you actually call dc, the __call__ method/function/property (whatever you want to name it) gets called, and it raises an exception just like you programmed it to. The traceback clearly shows __call__ in the stack. hasattr(type(dc), '__call__') returns true, therefore dc is callable. I think that the fact that the __call__ method ends up raising an AttributeError is irrelevant -- lots of callables raise AttributeError: def func(): return None.spam However, I think *this* is a bug in callable: py> class Callable: ... def __getattribute__(self, name): ... if name == '__call__': ... raise AttributeError # Oh the lies we tell. ... return super().__getattribute__(name) ... def __call__(self): ... return 23 ... py> x = Callable() py> callable(x) False py> x() 23 Clearly x is callable, since I just called it and it returned a value, but callable() thinks it is not. Here is another example: py> class X: pass ... py> x = X() py> x.__call__ = 42 py> callable(x) True py> x() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'X' object is not callable I think callable() is badly broken. (Or at least *was* broken in 3.3 -- I don't have 3.4 handy to try it.) -- Steve