What is a good way to order methods in a Python class?

Python

Python Problem Overview


I want to order methods in a Python class, but I don't know what the correct order is.

When I extract methods in Eclipse with PyDev, Eclipse puts the extracted method on top of the modified method. But this puts the lower level details before the higher level details. According to Uncle Bob, I should do the opposite, so that my code reads like the headlines of a newspaper. When I program in Java I just follow his advice.

What is the best practice for Python?

Python Solutions


Solution 1 - Python

As others have pointed out, there is no right way to order your methods. Maybe a PEP suggestion would be useful, but anyway. Let me try to approach your question as objectively as possible.

  • Interfaces first: Public methods and Python magic functions define the interface of the class. Most of the time, you and other developers want to use a class rather than change it. Thus they will be interested in the interface of that class. Putting it first in the source code avoids scrolling through implementation details you don't care about.

  • Properties, magic methods, public methods: It's hard to define the best order between those three, which are all part of the interface of the class. As Ethan Furman says, it's most important to stick with one system for the whole project. Generally, people expect __init__() to the best first function in the class so I follow up with the other magic methods right below.

  • Reading order: Basically, there are two ways to tell a story: Bottom-up or top-down. By putting high-level functions first, a developer can get a rough understanding of the class by reading the first couple of lines. Otherwise, one would have to read the whole class in order to get any understanding of the class and most developers don't have the time for that. As a rule of thumb, put methods above all methods called from their body.

  • Class methods and static methods: Usually, this is implied by the reading order explained above. Normal methods can call all methods times and thus come first. Class methods can only call class methods and static methods and come next. Static methods cannot call other methods of the class and come last.

Most of these rules are not Python-specific by the way. I'm not aware of a language that enforces method order.

Solution 2 - Python

There is no one correct order. Pick a system and stick with it. The one I use is:

class SomeClass(object):

    def __magic_methods__(self):
        "magic methods first, usually in alphabetical order"

    def _private_method(self):
        "worker methods next, also in alphabetical order"

    def a_method(self):
        "then normal methods, also in alphabetical order"

Solution 3 - Python

I do something similar to Ethan that I saw in Django's source, where the main difference is big "############" block comments to delimit the areas.

For example,

class SomeClass(object):

    #################
    # Magic Methods #
    #################
    def __magic_methods__(self):
        "magic methods first"

    ##################
    # Public Methods #
    ##################
    def a_method(self):
        "then normal methods, in order of importance"

    ###################
    # Private Methods #
    ###################
    def _private_method(self):
        "then worker methods, grouped by importance or related function"

Obviously this is less useful for smaller classes.

Solution 4 - Python

The code

class Bar(_Foo):
	pass

class _Foo:
	pass

raises an exception since the class _Foo has to be defined before it is used. You can find similar exception-raising example for functions too:

def bar(f=_foo):
	pass

def _foo():
	pass

Given these examples it makes sense to generally define private classes and functions before the public ones. That's why it makes sense to keep the consistency and to define also private methods before the public ones.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionzetafishView Question on Stackoverflow
Solution 1 - PythondanijarView Answer on Stackoverflow
Solution 2 - PythonEthan FurmanView Answer on Stackoverflow
Solution 3 - PythonMatt LuongoView Answer on Stackoverflow
Solution 4 - PythonJeyekomonView Answer on Stackoverflow