keeping a ref to a non-member function in a class

Gregory Bond gnb at itga.com.au
Tue Aug 16 20:32:20 EDT 2005


Peter Otten wrote:

> 
> You are on the right track with staticmethod, but you have to apply it to
> fn:
> 
> ...     fn = staticmethod(foo)


Thanks Peter, that's a big help.

I can solve my problem now, but I'm chasing this further in the name of 
education, because it seems there is some deep magic happening here that 
I don't understand.

It seems that applying staticfunction() (or perhaps assigning to the 
class object) is treated differently if it happens in the class 
defininition, to when it happens at "run time".  (My previous attempts 
to get staticmember() to do the right thing were all "run time" like the 
examples below.)

Say I wanted to keep the need for "staticmember" hidden from subclasses, 
and do the staticmember() conversion in the base class methods. I've 
tried 2 ways of doing this (no subclassing here, just to keep it simple):

> class B(object):
>     fn = foo
>     def try1(self):
>         print "B.fn is", type(B.fn)
>         B.fn = staticmethod(B.fn)
>         print "B try1"
>         print "B.fn is now", type(B.fn)
>         B.fn()
>         
>     def try2(self):
>         fn2 = staticmethod(B.fn)
>         print "B try2"
>         print "fn2 is now", type(fn2)
>         fn2()

If I try method 1 (assigning to the class object - ignore for a moment 
the problem of only doing this once!) I get a set of very surprising 
results:

> B.fn is <type 'instancemethod'>
> B try1
> B.fn is now <type 'instancemethod'>
> Traceback (most recent call last):
>   File "t_o1.py", line 28, in ?
>     B().try1()
>   File "t_o1.py", line 17, in try1
>     B.fn()
> TypeError: unbound method foo() must be called with B instance as first argument (got nothing instead)

note that assigning the staticmember() result to B.fn does NOT change 
the type of B.fn!!  And foo is treated as a member function.

So if I try method 2 (using staticmethod() at runtime):

> B try2
> fn2 is now <type 'staticmethod'>
> Traceback (most recent call last):
>   File "t_o1.py", line 27, in ?
>     B().try2()
>   File "t_o1.py", line 22, in try2
>     fn2()
> TypeError: 'staticmethod' object is not callable

fn2 is a static method, as I'd expect, but it is somehow not callable?

Can someone explain what is going on here?  Pointers to language spec, 
code, PEPs etc gladly accepted.

Greg,
caught in a twisty little maze of descriptors, all different!



More information about the Python-list mailing list