Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can someone explain how the source code of staticmethod works in python

First of all, I understand how, in general, a decorator work. And I know @staticmethod strips off the instance argument in the signature, making

class C(object):
    @staticmethod
    def foo():
        print 'foo'
C.foo    //<function foo at 0x10efd4050>
C().foo  //<function foo at 0x10efd4050>

valid.

However, I don't understand how the sourcec code of staticmethod make this happen.

It seems to me that when wrapping method foo in staticmethod, an instance of staticmethod is instantiated, then some magic happens, making C.foo() legit.

So.. what happen in those magic? what did staticmethod do?

I'm aware the enormous topics on SO regarding staticmethods but none of them addresses my doubts. But maybe I didn't hit the magic keyword. If so, please kindly let me know.

For whoever looking for staticmethod source code, please refer to https://hg.python.org/cpython/file/c6880edaf6f3/Objects/funcobject.c

like image 913
user2829759 Avatar asked Aug 10 '15 09:08

user2829759


People also ask

What does Staticmethod do in Python?

The staticmethod() returns a static method for a function passed as the parameter.

How do you call a Staticmethod function in Python?

If anything not using the decorator gives you a method that is more "static" because you can't even call it from an instance object. When you use @staticmethod you can call the method from both the class and class instance objects.

What is Staticmethod decorator in Python?

The @staticmethod is a built-in decorator that defines a static method in the class in Python. A static method doesn't receive any reference argument whether it is called by an instance of a class or by the class itself.

What is the purpose of Classmethod and Staticmethod in Python?

The difference between the Class method and the static method is: A class method takes cls as the first parameter while a static method needs no specific parameters. A class method can access or modify the class state while a static method can't access or modify it.


1 Answers

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?.

like image 132
Martijn Pieters Avatar answered Oct 06 '22 13:10

Martijn Pieters