Python has a concept of descriptor objects, which are objects having at least the __get__
method. These objects behave differently when retrieved from a class, or an instance, as attributes (their __get__
method is called.)
The @staticmethod
decorator transforms the subsequent function declaration in a descriptor that has the static method behavior - but said behavior will only be available when retrieving the object as a class attribute. The code above makes a direct reference to the object as it is, instead.
Since it is you also have other (class) methods for your dictionary to work, you'd better
retrieve yoiur desired methods after class creation, so that each method is retrieved via descriptor protocol:
class A(object):
@classmethod
def do_it(cls, spam, eggs):
if spam in A.ways_to_do_it:
A.ways_to_do_it[spam](eggs)
super(A, cls).do_it(spam, eggs)
@staticmetod
def do_it_somehow(eggs):
...
@staticmetod
def do_it_another_way(eggs):
...
A.ways_to_do_it = {
'somehow': A.do_it_somehow,
'another_way': A.do_it_another_way,
}
You could retrieve your static method before class creation, calling do_it_another_way.__get__(object, None)
- since it does not need the class reference (but needs a valid class as first parameter nonetheless). But if you want your dictionary to also point to the classmethods defined, they definitely have to be fetched after class creation: there is no way Python can create you a "bound class method" before class creation.
Creating other direct references to the class/static methods inside the class body works:
class A(object):
@staticmethod
def foo(): ...
bar = foo
because in this way, bar would also be fetched through the descriptor protocol. But since you have an indirect dictionary, you have to take care of the descriptor __get__
call yourself.
Check http://docs.python.org/2/reference/datamodel.html#implementing-descriptors for more information. (This is what the classmethod, staticmethod decorators do, since you also wanted to know).