Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why choose module level function over @staticmethod in Python (according to Google Style Guide)?

According to Google Python Style Guide, static methods should (almost) never be used:

Never use @staticmethod unless forced to in order to integrate with an API defined in an existing library. Write a module level function instead

What are the reasons behind such recommendation?

Is this particular to Google only or are there any other (more general) downsides with using static methods in Python?

Especially, what is the best practice if I want to implement an utility function inside of a class that will be called by other public member functions of that class?

class Foo: 
    .......
    def member_func(self): 
        some_utility_function(self.member)

google python style guide

like image 362
HanaKaze Avatar asked Aug 22 '18 21:08

HanaKaze


1 Answers

How to understand the Google Python Style Guide that says:

Never use @staticmethod unless forced to in order to integrate with an API defined in an existing library. Write a module level function instead

Well, you should understand it as Google's style guide. If you're writing Python code for Google, or contributing to a project that conforms to that style guide, or have chosen to use it for a project of your own, the answer is pretty simple: Don't use @staticmethod except when forced to by an API.

This means there are no judgment-call cases: A utility function inside of a class is not forced to be a @staticmethod by an API, so it should not be a @staticmethod.

The same is true for some other common1 reasons for @staticmethod. If you want a default value for an instance attribute that's meant to hold a callback function… too bad, find another way to write it (e.g., a local function defined inside __init__). If you want something that looks like a @classmethod but explicitly doesn't covary with subclasses… too bad, it just can't look like a @classmethod.


Of course if you're not following Google's style guide, then you should understand it as just one opinion among many. Plenty of Python developers aren't quite as hard against @staticmethod as that guide is. Of course Google is a pretty prominent developer of lots of Python code. On the other hand, Google's style guide was written while imported Java-isms were more of a problem than today.2 But you probably don't want to think too much about how much weight to give each opinion; instead, when it's important, learn the issues and come up with your own opinion.


As for your specific example, as I said in a comment: the fact that you naturally find yourself writing some_utility_function(self.member) instead of self.some_utility_function(self.member) or Foo.some_utility_function(self.member) means that intuitively, you're already thinking of it as a function, not a @staticmethod. In which case you should definitely write that one as a function, not a @staticmethod.

That may be just the opinion of one guy on the internet, but I think most Python developers would agree in this case. It's the times when you do naturally find yourself prefixing self. before every call when there's a judgment call to make.


1. Well, not exactly common. But they aren't so rare that they never come up. And they were common enough that, when there was discussion about deprecating @staticmethod for Python 3, someone quickly came up with these two cases, with examples from the standard library, and that was enough for Guido to kill the discussion.

2. In Java, there are no module-level functions, and you're forced to write static methods to simulate them. And there were a few years where most university CS programs were focused on Java, and a ton of software was written by Java, so tons of people were writing Python classes with way too many @staticmethods (and getters and setters, and other Java-isms).

like image 174
abarnert Avatar answered Sep 20 '22 05:09

abarnert