Am 17.11.2011 03:30 schrieb Roy Smith:
When I run this (python 2.6.1):

class C:
     @staticmethod
     def foo():
         pass

     print "inside", foo, callable(foo)

print "outside", C.foo, callable(C.foo)

I get:

inside<staticmethod object at 0x421df0>  False
outside<function foo at 0x41e6f0>  True

Right. The reason is that on an attribute access, you get a __get__ call of the "real" attribute.

That is, if your class has a "regular" method, it is stored there as a formal function. But if you access it (C.f), you get C.__dict__["f"].__get__(None, C) (not sure about the arguments, but you should get the idea).

A functions __get__ returns a unbound or bound method, depending on its own arguments.

With a static method, you don't want this to happen. So you wrap your "regular" function into a staticmethod object, which has a __get__() method itself just returning the wrapped function object.

Look at this:

>>> class C(object): pass
...
>>> f=lambda *a:a
>>> C.f=f
>>> s=staticmethod(f)
>>> C.s=s
>>> # Now we test the access
...
>>> f
<function <lambda> at 0x00B43E30>
>>> s
<staticmethod object at 0x00B48A90>
>>> C.f
<unbound method C.<lambda>>
>>> C().f
<bound method C.<lambda> of <__main__.C object at 0x00B48810>>
>>> C.s
<function <lambda> at 0x00B43E30>
>>> C().s
<function <lambda> at 0x00B43E30>
>>> f.__get__(None, C)
<unbound method C.<lambda>>
>>> f.__get__(C(), C)
<bound method C.<lambda> of <__main__.C object at 0x00B48AD0>>
>>> s.__get__(None, C)
<function <lambda> at 0x00B43E30>
>>> s.__get__(C(), C)
<function <lambda> at 0x00B43E30>


That's how things work.

If you want to get back the "real" function from a staticmethod, you either call its __get__ with an arbitrary argument, or you do it the clean way and do a

def deref(s):
    class C(object): s=s
    return s.s

and so do a

class User(Document):
     @staticmethod
     def _get_next_id():
       [blah, blah, blah]
       return id

     user_id = IntField(required=True, default=deref(_get_next_id))


HTH,


Thomas
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to