why different between staticmethod and classmethod on non-callable object?
hi all: In the svn thunk tree, I find in file Object/funcobject.c, the two functions: sm_init and cm_init have a little different. the cm_init function will check the object is really callable, but the sm_init don't. the code like this: if (!PyCallable_Check(callable)) { PyErr_Format(PyExc_TypeError, "'%s' object is not callable", callable->ob_type->tp_name); return -1; } so when use staticmethod and classmethod on a class variable, there are two different behavior. class Test(object): name = "s7v7nislands" name = classmethod(Test.name) # will raise error. name = staticmethod(Test.name) # will not raise error. My idea is: here, the two functions (or maybe classes) should have the same behavior). so is this a bug or something I missing ? thanks! s7v7nislands
2009/8/31 xiaobing jiang <s7v7nislands@gmail.com>:
My idea is: here, the two functions (or maybe classes) should have the same behavior). so is this a bug or something I missing ?
I think they should both not check their arguments in __init__ to allow for duck typing. -- Regards, Benjamin
On Tue, Sep 1, 2009 at 07:21, Benjamin Peterson<benjamin@python.org> wrote:
2009/8/31 xiaobing jiang <s7v7nislands@gmail.com>:
My idea is: here, the two functions (or maybe classes) should have the same behavior). so is this a bug or something I missing ?
I think they should both not check their arguments in __init__ to allow for duck typing.
But what is the point of wrapping something with classmethod or staticmethod that can't be called? It isn't like it is checking explicitly for a function or method, just that it can be called which seems reasonable to me (unless PyCallable_Check() is as off as callable() was). -Brett
2009/9/1 Brett Cannon <brett@python.org>:
On Tue, Sep 1, 2009 at 07:21, Benjamin Peterson<benjamin@python.org> wrote:
2009/8/31 xiaobing jiang <s7v7nislands@gmail.com>:
My idea is: here, the two functions (or maybe classes) should have the same behavior). so is this a bug or something I missing ?
I think they should both not check their arguments in __init__ to allow for duck typing.
But what is the point of wrapping something with classmethod or staticmethod that can't be called? It isn't like it is checking explicitly for a function or method, just that it can be called which seems reasonable to me (unless PyCallable_Check() is as off as callable() was).
Well, if checking if tp_call is not NULL is as bad as callable, then yes. I don't see any reason to use staticmethod or classmethod with a non-callable, but to be consistent, I would, given the choice between removing code and adding another type check, perfer to remove a type check. -- Regards, Benjamin
On Tue, Sep 1, 2009 at 14:54, Benjamin Peterson<benjamin@python.org> wrote:
2009/9/1 Brett Cannon <brett@python.org>:
On Tue, Sep 1, 2009 at 07:21, Benjamin Peterson<benjamin@python.org> wrote:
2009/8/31 xiaobing jiang <s7v7nislands@gmail.com>:
My idea is: here, the two functions (or maybe classes) should have the same behavior). so is this a bug or something I missing ?
I think they should both not check their arguments in __init__ to allow for duck typing.
But what is the point of wrapping something with classmethod or staticmethod that can't be called? It isn't like it is checking explicitly for a function or method, just that it can be called which seems reasonable to me (unless PyCallable_Check() is as off as callable() was).
Well, if checking if tp_call is not NULL is as bad as callable, then yes.
I don't see any reason to use staticmethod or classmethod with a non-callable, but to be consistent, I would, given the choice between removing code and adding another type check, perfer to remove a type check.
Fine by me. I guess it will just fail later with a slightly more cryptic exception. -Brett
On Sep 1, 2009, at 2:54 PM, Benjamin Peterson wrote:
2009/9/1 Brett Cannon <brett@python.org>:
On Tue, Sep 1, 2009 at 07:21, Benjamin Peterson<benjamin@python.org> wrote:
2009/8/31 xiaobing jiang <s7v7nislands@gmail.com>:
My idea is: here, the two functions (or maybe classes) should have the same behavior). so is this a bug or something I missing ?
I think they should both not check their arguments in __init__ to allow for duck typing.
But what is the point of wrapping something with classmethod or staticmethod that can't be called? It isn't like it is checking explicitly for a function or method, just that it can be called which seems reasonable to me (unless PyCallable_Check() is as off as callable() was).
Well, if checking if tp_call is not NULL is as bad as callable, then yes.
I don't see any reason to use staticmethod or classmethod with a non-callable, but to be consistent, I would, given the choice between removing code and adding another type check, perfer to remove a type check.
Removing the type check is also my preference. Raymond
Brett Cannon wrote:
It isn't like it is checking explicitly for a function or method, just that it can be called which seems reasonable to me (unless PyCallable_Check() is as off as callable() was).
I think it just checks that there's something in the tp_call slot, which is reasonable -- if it's empty, there's no way that calling the object could ever succeed, so you might as well fail early. -- Greg
2009/9/1 Greg Ewing <greg.ewing@canterbury.ac.nz>:
Brett Cannon wrote:
It isn't like it is checking explicitly for a function or method, just that it can be called which seems reasonable to me (unless PyCallable_Check() is as off as callable() was).
I think it just checks that there's something in the tp_call slot, which is reasonable -- if it's empty, there's no way that calling the object could ever succeed, so you might as well fail early.
It depends on whether you're keeping the "callable" object around or not. Somebody could add a __call__ method later. -- Regards, Benjamin
Benjamin Peterson wrote:
It depends on whether you're keeping the "callable" object around or not. Somebody could add a __call__ method later.
Good point. Removing the check sounds like the right thing to do, then. -- Greg
Greg Ewing wrote:
Benjamin Peterson wrote:
It depends on whether you're keeping the "callable" object around or not. Somebody could add a __call__ method later.
Good point. Removing the check sounds like the right thing to do, then.
Both classmethod & staticmethod are documented as having a *function* (callable, as I interprete that) as their single argument. Seems reasonable to me. Turning the argument into a function after the fact seems like a really esoteric use case.
At 08:50 PM 9/1/2009 -0400, Terry Reedy wrote:
Greg Ewing wrote:
Benjamin Peterson wrote:
It depends on whether you're keeping the "callable" object around or not. Somebody could add a __call__ method later. Good point. Removing the check sounds like the right thing to do, then.
Both classmethod & staticmethod are documented as having a *function* (callable, as I interprete that) as their single argument. Seems reasonable to me. Turning the argument into a function after the fact seems like a really esoteric use case.
The main use case for staticmethod is to prevent __get__ from being called on an object retrieved from a class or an instance. It just happens that the most common types of objects you'd want to do that on are functions. However, if for some reason you intend to make a *descriptor* available as an attribute (via a class default), then wrapping it with staticmethod is the only easy way to do it. For example, if you're writing a class whose instances have an attribute that holds a "property" instance, and you want to provide a class-level default, the simplest way to do it is to wrap the default property instance with staticmethod, so that it's not treated as a property of the class/instance. (Property instances are of course not callable.)
P.J. Eby wrote:
At 08:50 PM 9/1/2009 -0400, Terry Reedy wrote:
Greg Ewing wrote:
Benjamin Peterson wrote:
It depends on whether you're keeping the "callable" object around or not. Somebody could add a __call__ method later. Good point. Removing the check sounds like the right thing to do, then.
Both classmethod & staticmethod are documented as having a *function* (callable, as I interprete that) as their single argument. Seems reasonable to me. Turning the argument into a function after the fact seems like a really esoteric use case.
The main use case for staticmethod is to prevent __get__ from being called on an object retrieved from a class or an instance. It just happens that the most common types of objects you'd want to do that on are functions.
If so, then it is mis-named and mis-documented, and it seems to me that there is *a* rationale (not necessarily determinative) for the current difference in implementation.
However, if for some reason you intend to make a *descriptor* available as an attribute (via a class default), then wrapping it with staticmethod is the only easy way to do it.
For example, if you're writing a class whose instances have an attribute that holds a "property" instance, and you want to provide a class-level default, the simplest way to do it is to wrap the default property instance with staticmethod, so that it's not treated as a property of the class/instance.
(Property instances are of course not callable.)
So that it is a 'static object' in some sense, but not a static *method*. Thanks for the clarification and example. tjr
the three types: function, classmethod, staticmethod are descriptors. but staticmethod's __get__ return the orignal value, others return object of instancemethod. (from souce in Objects/funcobject.c) so the staticmethod just like a wrap that make the wrapped object 'frozen'. like in your example. is it right? the name and document are mis-understanded. thanks 2009/9/2 P.J. Eby <pje@telecommunity.com>:
At 08:50 PM 9/1/2009 -0400, Terry Reedy wrote:
Greg Ewing wrote:
Benjamin Peterson wrote:
It depends on whether you're keeping the "callable" object around or not. Somebody could add a __call__ method later.
Good point. Removing the check sounds like the right thing to do, then.
Both classmethod & staticmethod are documented as having a *function* (callable, as I interprete that) as their single argument. Seems reasonable to me. Turning the argument into a function after the fact seems like a really esoteric use case.
The main use case for staticmethod is to prevent __get__ from being called on an object retrieved from a class or an instance. It just happens that the most common types of objects you'd want to do that on are functions.
However, if for some reason you intend to make a *descriptor* available as an attribute (via a class default), then wrapping it with staticmethod is the only easy way to do it.
For example, if you're writing a class whose instances have an attribute that holds a "property" instance, and you want to provide a class-level default, the simplest way to do it is to wrap the default property instance with staticmethod, so that it's not treated as a property of the class/instance.
(Property instances are of course not callable.)
_______________________________________________ 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/s7v7nislands%40gmail.com
participants (7)
-
Benjamin Peterson
-
Brett Cannon
-
Greg Ewing
-
P.J. Eby
-
Raymond Hettinger
-
Terry Reedy
-
xiaobing jiang