First of all, I understand how, in general, a decorator work. And I know @staticmethod
strips off the instance argument in the signature, making
cla
A staticmethod
object is a descriptor. The magic you are missing is that Python calls the __get__
method when accessing the object as an attribute on a class or instance.
So accessing the object as C.foo
results in Python translating that to C.__dict__['foo'].__get__(None, C)
, while instance_of_C.foo
becomes type(instace_of_C).__dict__['foo'].__get__(instance_of_C, type(instance_of_C))
.
The staticmethod
object is defined in C code, but an equivalent in Python would be:
class staticmethod(object):
def __init__(self, callable):
self.f = callable
def __get__(self, obj, type=None):
return self.f
@property
def __func__(self):
return self.f
where self.f
is the original wrapped function.
All this is needed because functions are themselves descriptors too; it is the descriptor protocol that gives you method objects (see python bound and unbound method object for more details). Since they too have a __get__
method, without a staticmethod
object wrapping the function, a functionobj.__get__
call produces a method object instead, passing in a self
argument.
There is also a classmethod
, which uses the second argument to descriptor.__get__
to bind a function to the class, and then there are property
objects, which translate binding into a function call directly. See How does the @property decorator work?.