[Python-Dev] concerns regarding callable() method
Hi, I have seen in PEP 3100 that callable() function is planned to be removed in Python 3000 with this replacement: just call the object and catch the exception???. For one, the object (if it is callable) can raise exception itself, so you need to somehow to differentiate between exception raised inside its __call__ and exception raised if object is not callable to begin with. Additionally consider something like something.set_callback (x) Assume that set_callback() wants to check if `x' is callable at all, to raise exception early and make error tracking easier. Currently, you can assert callable (x) But if callable() is removed, there is no apparent replacement. Of course, you cannot call `x' since it might have side-effects or be slow etc. Please reconsider removal of callable() or provide an adequate replacement. Paul ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] concerns regarding callable() method
I have seen in PEP 3100 that callable() function is planned to be removed in Python 3000 with this replacement: just call the object and catch the exception???. For one, the object (if it is callable) can raise exception itself, so you need to somehow to differentiate between exception raised inside its __call__ and exception raised if object is not callable to begin with. I seem to recall bringing up the same issue a while ago; at the time, the answer was that if you need it, you can write your own: def callable(x): return hasattr(x, '__call__') My own preference would be for such queries to be defined abstractly as a built-in part of the language, but apparently my preference is out of sync with the community in this particular respect. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] concerns regarding callable() method
On 4/8/07, Paul Pogonyshev [EMAIL PROTECTED] wrote: I have seen in PEP 3100 that callable() function is planned to be removed in Python 3000 with this replacement: just call the object and catch the exception???. For one, the object (if it is callable) can raise exception itself, so you need to somehow to differentiate between exception raised inside its __call__ and exception raised if object is not callable to begin with. Why? Additionally consider something like something.set_callback (x) Assume that set_callback() wants to check if `x' is callable at all, to raise exception early and make error tracking easier. Currently, you can assert callable (x) But if callable() is removed, there is no apparent replacement. Of course, you cannot call `x' since it might have side-effects or be slow etc. assert hasattr(x, '__call__') I note that callable() was introduced before all callable objects had a __call__ attribute. This is no longer the case, so it's not needed. Please reconsider removal of callable() or provide an adequate replacement. What if someone passes a callable that doesn't have the expected signature? -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] concerns regarding callable() method
Guido van Rossum wrote: On 4/8/07, Paul Pogonyshev [EMAIL PROTECTED] wrote: Additionally consider something like something.set_callback (x) Assume that set_callback() wants to check if `x' is callable at all, to raise exception early and make error tracking easier. Currently, you can assert callable (x) But if callable() is removed, there is no apparent replacement. Of course, you cannot call `x' since it might have side-effects or be slow etc. assert hasattr(x, '__call__') I note that callable() was introduced before all callable objects had a __call__ attribute. This is no longer the case, so it's not needed. I just didn't think about that possibility. If that works the same way, callable() is just a sugar and not something unimplementable in other ways. Therefore, my objection is discarded. (But PEP 3100 should probably be update to mention this, otherwise you may get this complaint again ;) Please reconsider removal of callable() or provide an adequate replacement. What if someone passes a callable that doesn't have the expected signature? Well, I don't know a way to catch such situations now, so removing callable() will not make it worse (even if you don't know about hasattr trick above.) Paul ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] concerns regarding callable() method
On 4/8/07, Paul Pogonyshev [EMAIL PROTECTED] wrote: Guido van Rossum wrote: What if someone passes a callable that doesn't have the expected signature? Well, I don't know a way to catch such situations now, so removing callable() will not make it worse (even if you don't know about hasattr trick above.) My point is that it's futile to use callable() -- even if it passes, you have no assurance that you actually have a valid callback. So why bother with it at all? It's counter to the spirit of Python. If someone passes you a bad callback, they will see a traceback when you call it. Then they fix their program. That's how it's supposed to work. -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] concerns regarding callable() method
On 4/8/07, Paul Pogonyshev [EMAIL PROTECTED] wrote: assert hasattr(x, '__call__') I note that callable() was introduced before all callable objects had a __call__ attribute. This is no longer the case, so it's not needed. I just didn't think about that possibility. If that works the same way, callable() is just a sugar and not something unimplementable in other ways. Therefore, my objection is discarded. (But PEP 3100 should probably be update to mention this, otherwise you may get this complaint again ;) I whole-heartedly agree here, because people who start learning python (like me some time ago) usually learn that it's bad to test for __call__ (can't remember where I read about that though), and that we should always use callable() to be on a safe side. When I first heard that callable() was going to be removed I kinda panicked myself, it's good to know that at least there's still a way to be sure that object is callable or not... ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] concerns regarding callable() method
On 4/8/07, Guido van Rossum [EMAIL PROTECTED] wrote: On 4/8/07, Paul Pogonyshev [EMAIL PROTECTED] wrote: Guido van Rossum wrote: What if someone passes a callable that doesn't have the expected signature? Well, I don't know a way to catch such situations now, so removing callable() will not make it worse (even if you don't know about hasattr trick above.) My point is that it's futile to use callable() -- even if it passes, you have no assurance that you actually have a valid callback. So why bother with it at all? It's counter to the spirit of Python. If someone passes you a bad callback, they will see a traceback when you call it. Then they fix their program. That's how it's supposed to work. But what if you need to do different things based on argument is callable or not? Take for example Dependency Injection recipe: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/413268 It uses callable to differentiate whether it needs to use object as singleton or to instantiate it on each request. I'm sure there might be other uses for callable when it's really useful. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] concerns regarding callable() method
Guido van Rossum wrote: On 4/8/07, Paul Pogonyshev [EMAIL PROTECTED] wrote: Guido van Rossum wrote: What if someone passes a callable that doesn't have the expected signature? Well, I don't know a way to catch such situations now, so removing callable() will not make it worse (even if you don't know about hasattr trick above.) My point is that it's futile to use callable() -- even if it passes, you have no assurance that you actually have a valid callback. So why bother with it at all? It's counter to the spirit of Python. If someone passes you a bad callback, they will see a traceback when you call it. Then they fix their program. That's how it's supposed to work. I have no problems with Python being untyped. But I want that error stack traces provide some useful information as possible with reasonable effort and that errors happen as early as possible. In particular, stack trace should mention that error occured when you passed something wrong to set_callback() call and not in some obscure place 200 lines later, because otherwise it will only obfuscate error reason. Yes, assert will not catch all errors, but at least it will some. I consider it perfectly acceptable that you cannot test signature, because (since Python is untyped) you could only test number of arguments and even that would probably involve dumb syntax. So, I understand such assert will not catch all errors. But I don't want to remove it, since I find catching at least some errors (e.g. like passing None) an improvement over catching no errors. Paul ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] concerns regarding callable() method
Guido van Rossum [EMAIL PROTECTED] wrote: On 4/8/07, Paul Pogonyshev [EMAIL PROTECTED] wrote: Guido van Rossum wrote: What if someone passes a callable that doesn't have the expected signature? Well, I don't know a way to catch such situations now, so removing callable() will not make it worse (even if you don't know about hasattr trick above.) My point is that it's futile to use callable() -- even if it passes, you have no assurance that you actually have a valid callback. So why bother with it at all? It's counter to the spirit of Python. If someone passes you a bad callback, they will see a traceback when you call it. Then they fix their program. That's how it's supposed to work. The point of using callable(x), or it's equivalent now of hasattr(x, '__call__') is to reduce reduce the time/lines of code between when an error occurs and when it is reported. Errors should never pass silently. While we currently cannot verify that some callable takes the proper arguments, number of arguments, etc., we *can* verify that it is callable. I think this is a good thing, as allowing the assignment of a non-callable to a name that is supposed to be callable is the silent passing of an error. With relatively minimal effort in Python 3, one could use a function signature object (PEPs 3107 and 362) to verify that a callable takes the proper number of arguments, expected keyword arguments, etc., which while still not allowing one to verify that the implementation of a callback is correct (technically impossible), it does get us closer to being able to know whether a callable is or may not be crap when it is assigned. If you still think that these two operations are undesireable (testing the callability, and that a callable takes certain arguments), that's fine (I disagree completely). But unless we mangle callables to not support these operations, people are probably going to do them anyways; especially those who are using annotations, function signature objects, etc., in their various frameworks. But maybe I'm misreading or reading to much into your statement of If someone passes you a bad callback, they will see a traceback when you call it. Then they fix their program. That's how it's supposed to work. - Josiah ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] concerns regarding callable() method
At 08:01 PM 4/8/2007 +0400, Alexey Borzenkov wrote: On 4/8/07, Guido van Rossum [EMAIL PROTECTED] wrote: On 4/8/07, Paul Pogonyshev [EMAIL PROTECTED] wrote: Guido van Rossum wrote: What if someone passes a callable that doesn't have the expected signature? Well, I don't know a way to catch such situations now, so removing callable() will not make it worse (even if you don't know about hasattr trick above.) My point is that it's futile to use callable() -- even if it passes, you have no assurance that you actually have a valid callback. So why bother with it at all? It's counter to the spirit of Python. If someone passes you a bad callback, they will see a traceback when you call it. Then they fix their program. That's how it's supposed to work. But what if you need to do different things based on argument is callable or not? Then delegate that behavior to the object using adaptation or a generic function. That is, use *table-driven* code, rather than if-then based code. Take for example Dependency Injection recipe: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/413268 It uses callable to differentiate whether it needs to use object as singleton or to instantiate it on each request. And that's a *bad* thing. What if I want to have a callable singleton? Or what if I want to have a singleton that gets notified of each request? With table-driven code (adaptation, generic functions) I can support the first case by reregistering an existing handler, and the second by registering my own handler. If-then based introspection is harmful here, because it's an attempt to *guess* what should be done with the object. Explicit is better than implicit, and it's better not to guess. callable(), like hasattr() or any other interface probing is essentially an attempt to guess at the callers intent, instead of providing a reasonable default that they can override. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] concerns regarding callable() method
On 4/8/07, Josiah Carlson [EMAIL PROTECTED] wrote: Guido van Rossum [EMAIL PROTECTED] wrote: On 4/8/07, Paul Pogonyshev [EMAIL PROTECTED] wrote: Guido van Rossum wrote: What if someone passes a callable that doesn't have the expected signature? Well, I don't know a way to catch such situations now, so removing callable() will not make it worse (even if you don't know about hasattr trick above.) My point is that it's futile to use callable() -- even if it passes, you have no assurance that you actually have a valid callback. So why bother with it at all? It's counter to the spirit of Python. If someone passes you a bad callback, they will see a traceback when you call it. Then they fix their program. That's how it's supposed to work. The point of using callable(x), or it's equivalent now of hasattr(x, '__call__') is to reduce reduce the time/lines of code between when an error occurs and when it is reported. Errors should never pass silently. I'm not sure if that argument weighs much (taken a bit farther it would require static typing :-). Two arguments made earlier are stronger IMO: - The traceback can be much clearer if it comes from setcallback(x) rather than from the actual call, much later. - The pragmatic ability (which often occurs in DWIM-ish behavior in template systems) to do different things depending on whether something is callable or not. (While in theory I agree with Phillip's objection that this should be dealt with in a more systematic way, in practice, at least for Python 2.x, I think it's an okay thing to do.) But the same thing can be said for properties like iterable, or hashable, and other primitive operations. FWIW, I haven't given up on doing something with abstract base classes here. I think they (or interfaces or generic functions, for that matter :-) provide a more systematic approach than either callable() or hasattr(x, __call__). TBC, --Guido While we currently cannot verify that some callable takes the proper arguments, number of arguments, etc., we *can* verify that it is callable. I think this is a good thing, as allowing the assignment of a non-callable to a name that is supposed to be callable is the silent passing of an error. With relatively minimal effort in Python 3, one could use a function signature object (PEPs 3107 and 362) to verify that a callable takes the proper number of arguments, expected keyword arguments, etc., which while still not allowing one to verify that the implementation of a callback is correct (technically impossible), it does get us closer to being able to know whether a callable is or may not be crap when it is assigned. If you still think that these two operations are undesireable (testing the callability, and that a callable takes certain arguments), that's fine (I disagree completely). But unless we mangle callables to not support these operations, people are probably going to do them anyways; especially those who are using annotations, function signature objects, etc., in their various frameworks. But maybe I'm misreading or reading to much into your statement of If someone passes you a bad callback, they will see a traceback when you call it. Then they fix their program. That's how it's supposed to work. - Josiah -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] concerns regarding callable() method
On 4/8/07, Paul Pogonyshev [EMAIL PROTECTED] wrote: I have no problems with Python being untyped. But I want that error stack traces provide some useful information as possible with reasonable effort and that errors happen as early as possible. In particular, stack trace should mention that error occured when you passed something wrong to set_callback() call and not in some obscure place 200 lines later, because otherwise it will only obfuscate error reason. Using the duck typing philosophy; if it quacks like a duck and walks like a duck, then it probably is a duck. But how can you be so sure it is NOT a duck if you have never seen it walk or heard it quack? What if you are passing in an object that is not callable but later on becomes callable? Is it really an error? I think the plan is that in py3k, you will be able to do type-checking using function annotations (bleach). Like this: def set_callback(self, callback : CallableType): self.callback = callback You probably also need to add some more gunk to make it work. I believe it should be able to replace most uses of callable(). -- mvh Björn ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] concerns regarding callable() method
Guido My point is that it's futile to use callable() -- even if it Guido passes, you have no assurance that you actually have a valid Guido callback. So why bother with it at all? It's counter to the Guido spirit of Python. If someone passes you a bad callback, they will Guido see a traceback when you call it. Then they fix their Guido program. That's how it's supposed to work. There's one place where I find the traceback somewhat unhelpful. Consider calling a method of a class with incorrect arguments: class C: ... def __init__(self): ... pass ... C(1) Traceback (most recent call last): File stdin, line 1, in module TypeError: __init__() takes exactly 1 argument (2 given) While in this example it's clear what method wasn't called correctly, a callback called with the wrong number of arguments yields a fairly useless stack trace. I'm thinking in particular of callbacks called from C code (e.g. Gtk signal handlers). I think it would be helpful to check to see if the function being called had an im_class attribute. If so, then resolve the class name and include it in the TypeError message: TypeError: C.__init__() takes exactly 1 argument (2 given) Skip ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com