Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does the decorator @staticmethod in Python get rid of the instance object?

As far as I have understood, a decorator is a function that takes another function as a parameter, performs some operation on it and then returns it.

Talking about the decorator @staticmethod, what exactly does that decorator do to eliminate the instance object that is being passed by default ?

like image 954
Febin Peter Avatar asked Dec 05 '25 10:12

Febin Peter


1 Answers

The staticmethod decorator returns a staticmethod object. This object implements the descriptor protocol, same as functions do.

What this does is not that it gets rid of the instance, instead the staticmethod.__get__ ignores binding altogether and just returns the unaltered function object. For regular functions, function.__get__ would instead bind by returning a method object (which then tracks the instance and the function to combine them when called).

You can reproduce this by manually invoking the descriptor protocol:

>>> class Demo:
...     def regular(self):
...         pass
...     @staticmethod
...     def static():
...         pass
...
>>> Demo.__dict__['regular']  # bypass __getattribute__
<function Demo.regular at 0x108515268>
>>> Demo.__dict__['static']   # bypass __getattribute__
<staticmethod object at 0x1084d4f60>
>>> Demo.__dict__['regular'].__get__(Demo())  # descriptor protocol, pass in an instance
<bound method Demo.regular of <__main__.Demo object at 0x1084e2668>>
>>> Demo.__dict__['static'].__get__(Demo())  # descriptor protocol, pass in an instance
<function Demo.static at 0x1085152f0>

By accessing the attributes of the Demo class through Demo.__dict__, we bypass the descriptor protocol normally enforced by the __getattribute__ method. As you can see, for a regular method a function object is returned, but for static a staticmethod object is found instead.

Calling .__get__(Demo()) on either to invoke the descriptor protocol then produces a method object, and the un-altered function object, respectively. This is exactly what direct access to the same names on an instance produces:

>>> Demo().regular
<bound method Demo.regular of <__main__.Demo object at 0x1084dde10>>
>>> Demo().static
<function Demo.static at 0x1085152f0>

Note that the same protocol is also the reason that classmethod objects are passed type(instance) instead of the instance as a first argument, and also why property objects call the underlying function on access.

like image 111
Martijn Pieters Avatar answered Dec 07 '25 23:12

Martijn Pieters



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!