Static method object not callable

Bengt Richter bokr at oz.net
Thu Aug 12 07:26:20 CEST 2004


On Thu, 12 Aug 2004 02:07:31 GMT, "Edward Diener" <eldiener at earthlink.net> wrote:

>Bengt Richter wrote:
>> 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?
>>>>>
>Yes. I understand now why it won't work but I think this is a limitation of
>Python. Evidently, if I set up my class attribute 'ad' to be "ad = { 1 :
>X.Y }", then calling static method X.Y through "self.ad[1](3)" would work.
>But Python does not allow me to say 'X.Y' from within a class attribute of X
>because X has not been fully defined as a class at that time. As one person
>answered, I can say "X.ad = { 1 : X.Y }" after the definition of class X and
>that works fine. But that is very kludgy to me, forcing me to wait until the
>definition of X is finished in order to create my ad class attribute.
>
>I thank you very much for the explanation of _get_ and how static methods
>work in Python. It still feels unnatural not to be able to reference a class
>attribute of a class in another class attribute of the same class from
>within the class definition.
>
>
Ok, got a couple things done. Reward time = play with python a little ;-)

Since ad is an attribute, you could give *it* some magic, if you wanted
to get your effect. Taking a cue from staticmethod and property etc, we'll
call it dienerize, and you use it to dienerize a dict class variable, analogous
to method = staticmethod(method). Then dict values that are descriptors will be
called to see what reading them as attributes would produce. Non-descriptor dict
values just come through plain. I added a  2:'ordinary' example in the dict, and
3:Z to refer to an ordinary method, which is a function-valued class variable, but
functions all have __get__ methods, so they become transformed when they are
accessed as attributes (or the equivalent magic). I had do move the ad definition
so the Z name reference was valid.

I'm living with your capitalized method names through gritted teeth ;-)
Also added X.W to help show some effects. Don't take this as gospel, it's
the first time I tried this twist on a descriptor ;-)

----< diener.py >--------------------
#diener.py
class dienerize(dict):
    def __getitem__(self, key):
        value = dict.__getitem__(self, key)
        if not hasattr(value, '__get__'): return value
        return value.__get__(*self.getargs)
    def __get__(self, *getargs):
        self.getargs = getargs
        return self # which should act like magic dict
        
class X(object):
  def Y(x):
    print x
  Y = staticmethod(Y)
  def Z(self):
    self.ad[1](3)
  ad = { 1 : Y, 2: 'ordinary', 3: Z }
  ad = dienerize(ad)
  def W(self, *args):
    for i,arg in enumerate(args):
        self.ad[1]('arg %2s: %r'%(i,arg)) # use Y for printing ;-)
x = X()
x.Z()
x.W(1,2,3)
x.W(X.Y, X.__dict__['Y'], x.ad[2], X.ad[2])
x.W(X.ad, X.__dict__['ad'], x.ad[1], X.ad[1])
x.W(x.ad[1], x.ad[2], x.ad[3]) # note that 3:Z becomes bound
x.W(x.ad[3],' ^--x.ad[3]',X.ad[3],' ^--X.ad[3]', x.__class__.__dict__['Z'],
" ^--x.__class__.__dict__['Z']")
print "Done."
-------------------------------------

Running it:

[22:18] C:\pywk\sovm>diener.py
3
arg  0: 1
arg  1: 2
arg  2: 3
arg  0: <function Y at 0x008FDEB0>
arg  1: <staticmethod object at 0x009013B0>
arg  2: 'ordinary'
arg  3: 'ordinary'
arg  0: {1: <staticmethod object at 0x009013B0>, 2: 'ordinary', 3: <function Z at 0x008FDEF0>}
arg  1: {1: <staticmethod object at 0x009013B0>, 2: 'ordinary', 3: <function Z at 0x008FDEF0>}
arg  2: <function Y at 0x008FDEB0>
arg  3: <function Y at 0x008FDEB0>
arg  0: <function Y at 0x008FDEB0>
arg  1: 'ordinary'
arg  2: <bound method X.Z of <__main__.X object at 0x00901390>>
arg  0: <bound method X.Z of <__main__.X object at 0x00901390>>
arg  1: ' ^--x.ad[3]'
arg  2: <unbound method X.Z>
arg  3: ' ^--X.ad[3]'
arg  4: <function Z at 0x008FDEF0>
arg  5: " ^--x.__class__.__dict__['Z']"
Done.

Since you now know why the original "didn't work" I figure you will know
why this one appears to ;-)

Gotta go.

Regards,
Bengt Richter



More information about the Python-list mailing list