Module function vs staticmethod vs classmethod vs no decorators: Which idiom is more pythonic? Module function vs staticmethod vs classmethod vs no decorators: Which idiom is more pythonic? python python

Module function vs staticmethod vs classmethod vs no decorators: Which idiom is more pythonic?


The most straightforward way to think about it is to think in terms of what type of object the method needs in order to do its work. If your method needs access to an instance, make it a regular method. If it needs access to the class, make it a classmethod. If it doesn't need access to the class or the instance, make it a function. There is rarely a need to make something a staticmethod, but if you find you want a function to be "grouped" with a class (e.g., so it can be overridden) even though it doesn't need access to the class, I guess you could make it a staticmethod.

I would add that putting functions at the module level doesn't "pollute" the namespace. If the functions are meant to be used, they're not polluting the namespace, they're using it just as it should be used. Functions are legitimate objects in a module, just like classes or anything else. There's no reason to hide a function in a class if it doesn't have any reason to be there.


Great answer by BrenBarn, but I would change 'If it doesn't need access to the class or the instance, make it a function' to:

'If it doesn't need access to the class or the instance...but is thematically related to the class (typical example: helper functions and conversion functions used by other class methods or used by alternate constructors), then use staticmethod

else make it a module function


This is not really an answer, but rather a lengthy comment:

Even more puzzling is that this code:

        class A:            def foo(x):                print(x)        A.foo(5)

Fails as expected in Python 2.7.3 but works fine in 3.2.3 (although you can't call the method on an instance of A, only on the class.)

I'll try to explain what happens here.

This is, strictly speaking, an abuse of the "normal" instance method protocol.

What you define here is a method, but with the first (and only) parameter not named self, but x. Of course you can call the method in an instance of A, but you'll have to call it like this:

A().foo()

or

a = A()a.foo()

so the instance is given to the function as first argument.

The possibility to call regular methods via the class has always been there and works by

a = A()A.foo(a)

Here, as you call the method of the class rather than on the instance, it doesn't get its first parameter given automaticvally, but you'll have to provide it.

As long as this is an instance of A, everything is ok. Giving it something else is IMO an abuse of the protocol, and thus the difference between Py2 and Py3:

In Py2, A.foo gets transformed to an unbound method and thus requires its first argument be an instance of the class it "lives" in. Calling it with something else will fail.

In Py3, this check has been dropped and A.foo is just the original function object. So you can call it with everything as first argument, but I wouldn't do it. The first parameter of a method should always be named self and have the semantics of self.