Static method object not callable
Bengt Richter
bokr at oz.net
Wed Aug 11 00:48:56 EDT 2004
On Wed, 11 Aug 2004 02:40:07 GMT, "Edward Diener" <eldiener at earthlink.net> wrote:
>Paul Morrow wrote:
>> Edward Diener wrote:
>>> This simple code example gives me the message, "TypeError:
>>> 'staticmethod' object is not callable".
>>>
>>> class X(object):
>>> def Y(x):
>>> print x
>>> Y = staticmethod(Y)
>>> ad = { 1 : Y }
>>> def Z(self):
>>> self.ad[1](3)
>>> x = X()
>>> x.Z()
>>> print "Done."
>>>
>>> I know there must be a way to have a class attribute reference a
>>> static method, and then call that static method through the
>>> reference, so if anyone can correct this it would be appreciated.
By 'reference' are you referring to the Y in ad?
>>>
>>>
>>>
>>
>> Here are two alternatives. snip...
>
>Neither alternative is satisfactory. Surely there must be some means of
>directly specifying a reference to a static method in a class attribute in
>Python, and calling it from an instance method through the class attribute.
>
>
I'm not sure what you really want, but a staticmethod object is UIAM a descriptor
and when descriptors are retrieved as attributes of something, their __get__ methods
are called. That's why getattr was part of the other alternatives. Alternatively,
you can call the __get__ method directly, and in the case of staticmethod, that
will get you back the unadorned function in question, which you can then call. E.g.,
>>> class X(object):
... def Y(x):
... print x
... Y = staticmethod(Y)
... ad = { 1 : Y }
... def Z(self):
... self.ad[1].__get__(self, type(self))(3)
...
>>> x = X()
>>> x.Z()
3
(BTW, for staticmethod.__get__, probably any argument(s)
other than None or None,None will work)
Maybe this will clarify a little:
A function also works like a descriptor, and has a __get__ method, which is called
to create a bound method when the function is retrieved as an attribute of an
object instance. Note that Z is a function with one argument (self).
When retrieving Z as attribute of the class, the __get__ method gets
the arguments __get__(None, X), which gets you the unbound method.
>>> X.Z
<unbound method X.Z>
If we bypass the attribute access mechanism, we get the function itself:
>>> X.__dict__['Z']
<function Z at 0x009062B0>
If we do the getattr mechanics manually, calling the __get__ of the function,
we see the method results corresponding to X.Z and x.Z respectively:
>>> X.__dict__['Z'].__get__(None, X)
<unbound method X.Z>
>>> X.__dict__['Z'].__get__(x, X)
<bound method X.Z of <__main__.X object at 0x009011D0>>
We can make a hokey descriptor object to show this:
>>> class Desc(object):
... def __get__(*args): print args
...
>>> class C(object):
... attr = Desc()
...
>>> c = C()
>>> C.attr
(<__main__.Desc object at 0x009015D0>, None, <class '__main__.C'>)
>>> c.attr
(<__main__.Desc object at 0x009015D0>, <__main__.C object at 0x00901950>, <class '__main__.C'>)
So the __get__ args are the self of the decriptor instance itself (handy for carrying baggage like
a function), and here either None,C or c,C for C.attr and c.attr repectively.
Y is a staticmethod object though, not a plain function.
The __get__ method of a staticmethod object returns the same thing
(the original function) for either kind of call.
So when retrieved as an attribute of something, you get the function in question:
>>> X.Y
<function Y at 0x008FDF70>
>>> x.Y
<function Y at 0x008FDF70>
Bypassing attribute mechanism:
>>> X.__dict__['Y']
<staticmethod object at 0x00901110>
Doing it manually bound-method style or unbound-method style:
>>> X.__dict__['Y'].__get__(x, X)
<function Y at 0x008FDF70>
>>> X.__dict__['Y'].__get__(None, X)
<function Y at 0x008FDF70>
Calling the retrieved function:
>>> X.__dict__['Y'].__get__(x, X)(123)
123
Of course,
>>> X.Y(456)
456
>>> x.Y(456)
456
or
>>> getattr(X,'Y')(789)
789
>>> getattr(x,'Y')(789)
789
I still don't know what you are really trying to do with that
Z method and the ad dict ;-)
Regards,
Bengt Richter
More information about the Python-list
mailing list