Search code examples
pythonclassmethodsstatic-methodsclass-method

Why is a method of a Python class declared without "self" and without decorators not raising an exception?


I thought that the following code would result in an error because as far as I have read, a method in a Python class must either have "self" (or any other label, but "self" by convention) as its first argument, or "cls" or similar if the @classmethod decorator is used, or none if the @staticmethod decorator is used.

How come I get no error running this with Python 3.5 in the Terminal, even though test_method does not meet these requirements? It seems to work fine as a static method, but without the decorator.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys

class MyClass:

    def test_method(args):
        print(args[1])

    @staticmethod
    def static_method():
        print("static_method")

    @classmethod
    def class_method(cls):
        print("class_method")


def main(args):
    MyClass.test_method(args)


if __name__ == '__main__':
    sys.exit(main(sys.argv))

Output:

$ python3 testscript.py "testing"
$ testing

EDIT:

My question could also be phrased differently, drawing attention away from self and to @staticmethod: "How come I'm getting a seemingly working static method without the @staticmethod decorator?"


Solution

  • In Python 2, functions defined in a class body are automatically converted to "unbound methods", and cannot be called directly without a staticmethod decorator. In Python 3, this concept was removed; MyClass.text_method is a simple function that lives inside the MyClass namespace, and can be called directly.

    The main reason to still use staticmethod in Python 3 is if you also want to call the method on an instance. If you don't use the decorator, the method will always be passed the instance as the first parameter, causing a TypeError.