Nicolas Fleury wrote: > Hi everyone, > I was wondering if it would make sense to make staticmethod objects > callable, so that the following code would work:
This is one of the more unintuitive areas of Python, with side effects and different behaviour depending on whether code is called inside or outside a class: >>> class Parrot: ... def speak(): ... return "dead parrot" ... speak = staticmethod(speak) ... def playdead(): ... return "still dead" ... >>> type(Parrot.speak) <type 'function'> >>> type(Parrot.playdead) <type 'instancemethod'> So, based on this evidence, staticmethod() converts an instance method into an ordinary function. Parrot.speak certainly behaves like an ordinary function. >>> callable(Parrot.speak) True >>> Parrot.speak() 'dead parrot' But now try to do the same outside of a class: >>> f = staticmethod(Parrot.playdead) >>> type(f) <type 'staticmethod'> f is not a function? >>> Parrot.playdead = staticmethod(Parrot.playdead) >>> type(Parrot.playdead) <type 'instancemethod'> So, based on this evidence, staticmethod() inside a class definition converts instance methods to functions. Outside a class definition, staticmethod() does one of two things: it either converts an instance method to a static method, or if the output is assigned to a class attribute, it leaves it as an instance method. Hmmm. > class A: > @staticmethod > def foo(): pass > bar = foo() Here is a work around: >>> class A: ... def foo(): return "foo foo foo" ... foo = staticmethod(foo) ... def __init__(self): ... if not hasattr(self.__class__, "bar"): ... self.__class__.bar = self.foo() ... >>> dir(A) ['__doc__', '__init__', '__module__', 'foo'] >>> a = A() >>> dir(A) ['__doc__', '__init__', '__module__', 'bar', 'foo'] >>> a.foo() 'foo foo foo' >>> a.bar 'foo foo foo' Here is a more interesting example: >>> class B: ... def foo(): ... return lambda x: x+1 ... foo = staticmethod(foo) ... def __init__(self): ... if not hasattr(self.__class__, "bar"): ... self.__class__.bar = \ ... staticmethod(self.foo()) ... >>> dir(B) ['__doc__', '__init__', '__module__', 'foo'] >>> b = B() >>> dir(B) ['__doc__', '__init__', '__module__', 'bar', 'foo'] >>> b.foo() <function <lambda> at 0xb7f70c6c> >>> b.bar <function <lambda> at 0xb7f70c34> >>> b.bar(3) 4 Hope this helps. -- Steven. -- http://mail.python.org/mailman/listinfo/python-list