36

There has been a discussion in chat relating to a question (the question itself being irrelevant to this one), that has revealed I may not know Python whatsoever.

In my mind, although terminology differs across languages, we may generally categorise functions as:

  • [free] functions
  • static methods / static member functions
  • non-static methods / non-static member functions

Apparently in Python there is another kind of function that doesn't fit into the above categories, one that is a method but "doesn't know its class".

What are "class methods" and "instance methods", in Python?

46

The short answer

  • an instance method knows its instance (and from that, its class)
  • a class method knows its class
  • a static method doesn't know its class or instance

The long answer

Class methods

A class method is one that belongs to the class as a whole. It doesn't require an instance. Instead, the class will automatically be sent as the first argument. A class method is declared with the @classmethod decorator.

For example:

class Foo(object):
    @classmethod
    def hello(cls):
        print("hello from %s" % cls.__name__)
Foo.hello()
-> "Hello from Foo"
Foo().hello()
-> "Hello from Foo"

Instance Methods

On the other hand, an instance method requires an instance in order to call it, and requires no decorator. This is by far the most common type of method.

class Foo(object):
    def hello(self):
        print("hello from %s" % self.__class__.__name__)
Foo.hello()
-> TypeError: hello() missing 1 required positional argument: 'self'

(note: the above is with python3; with python2 you'll get a slightly different error)

Static methods

A static method is similar to a class method, but won't get the class object as an automatic parameter. It is created by using the @staticmethod decorator.

class Foo(object):
    @staticmethod
    def hello(cls):
        print("hello from %s" % cls.__name__)

Foo.hello()
-> TypeError: hello() missing 1 required positional argument: 'cls'

Documentation links

Here are links to the relevant python3 documentaton:

The data model documentation has this to say about the difference between class methods and static methods:

Static method objects Static method objects provide a way of defeating the transformation of function objects to method objects described above. A static method object is a wrapper around any other object, usually a user-defined method object. When a static method object is retrieved from a class or a class instance, the object actually returned is the wrapped object, which is not subject to any further transformation. Static method objects are not themselves callable, although the objects they wrap usually are. Static method objects are created by the built-in staticmethod() constructor.

Class method objects A class method object, like a static method object, is a wrapper around another object that alters the way in which that object is retrieved from classes and class instances. The behaviour of class method objects upon such retrieval is described above, under “User-defined methods”. Class method objects are created by the built-in classmethod() constructor.

Related questions

  • 4
    @LightnessRacesinOrbit: I don't think static methods are used particularly often in python. Using my system as an random sample, when I search through all of the packages I have installed, only about 1% of all methods are static methods (which frankly was more than I was expecting). – Bryan Oakley Dec 29 '15 at 15:42
  • 1
    "Static methods" are usually a code smell, and are discouraged by e.g. Gogole Python style guide. – 9000 Dec 29 '15 at 16:46
  • 3
    I think the answer would better if it drew attention to subclasses, which is where classmethods get some usefulness. – Winston Ewert Dec 29 '15 at 17:20
  • 1
    @user2357112: I simply counted all instances of "^ def(", then counted all instances of @staticmethod. Very unscientific, but probably was within the ballpark. – Bryan Oakley Dec 29 '15 at 18:15
  • 2
    @Kashyap: the TL;DR applies to the very first paragraph. I think it works better at the top than the bottom. – Bryan Oakley Dec 29 '15 at 21:49
8

What are “class methods” and “instance methods”, in Python?

  • An "instance method" uses the information contained in the instance to figure out what value to return (or which side-effect to do). These are very common.

  • A "class method" uses information about the class (and not an instance of that class) to affect what it does (they're typically used to create new instances as alternative constructors, and thus aren't incredibly common).

  • A "static method" doesn't use any information about the class or instance to calculate what it does. It is usually just in the class for convenience. (As such, these aren't very common either.)

A Function of X

Remember math class, "y is a function of x, f(x)?" Let's apply that in code:

y = function(x)

Implied by the above is that since x may change, y may change when x changes. This is what is meant when we say that "y is a function of x"

What will y be when z is 1? 2? 'FooBarBaz'?

y is not a function of z, so z can be anything and not affect the outcome of the function assuming our function is a pure function. (If it accesses z as a global variable, then it's not a pure function - this is what is meant by functional purity.)

Keep the above in mind as you read the following descriptions:

Instance Methods

An instance method is function that is a function of an instance. The function accepts the instance implicitly as an argument to it, and the instance is used by the function to determine the output of the function.

A built-in example of an instance method is str.lower:

>>> 'ABC'.lower()
'abc'

str.lower is called on the instance of the string, and it uses the information contained in the instance to figure out which new string to return.

Class Methods:

Remember, in Python, everything is an object. That means the class is an object, and can be passed as an argument to a function.

A class method is a function that is a function of the class. It accepts the class as an argument to it.

A builtin example is dict.fromkeys:

>>> dict.fromkeys('ABC')
{'C': None, 'B': None, 'A': None}

The function implicitly knows its own class, the function uses the class to affects the output of the function, and it creates a new one of that class from the iterable. An OrderedDict demonstrates this when using the same method:

>>> from collections import OrderedDict
>>> OrderedDict.fromkeys('ABC')
OrderedDict([('A', None), ('B', None), ('C', None)])

The class method uses information about the class (and not an instance of that class) to affect what type of class to return.

Static Methods

You mention a method that "doesn't know its class" - this is a static method in Python. It is merely attached for convenience to the class object. It could optionally be a separate function in another module, but its call signature would be the same.

A static method is a function of neither the class nor the object.

A built-in example of a static method is str.maketrans from Python 3.

>>> str.maketrans('abc', 'bca')
{97: 98, 98: 99, 99: 97}

Given a couple of arguments, it makes a dictionary that is not a function of its class.

It is convenient because str is always available in the global namespace, so you can easily use it with the translate function:

>>> 'abracadabra'.translate(str.maketrans('abc', 'bca'))
'bcrbabdbcrb'

In Python 2, you have to access it from the string module:

>>> 'abracadabra'.translate(str.maketrans('abc', 'bca'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'str' has no attribute 'maketrans'
>>> import string
>>> 'abracadabra'.translate(string.maketrans('abc', 'bca'))
'bcrbabdbcrb'

Example

class AClass(object):
    """In Python, a class may have several types of methods: 
    instance methods, class methods, and static methods
    """

    def an_instance_method(self, x, y, z=None):
        """this is a function of the instance of the object
        self is the object's instance
        """
        return self.a_class_method(x, y)

    @classmethod
    def a_class_method(cls, x, y, z=None):
        """this is a function of the class of the object
        cls is the object's class
        """
        return cls.a_static_method(x, y, z=z)

    @staticmethod
    def a_static_method(x, y, z=None):
        """this is neither a function of the instance or class to 
        which it is attached
        """
        return x, y, z

Let's instantiate:

>>> instance = AClass()

Now the instance can call all of the methods:

>>> instance.an_instance_method('x', 'y')
('x', 'y', None)
>>> instance.a_static_method('x', 'y')
('x', 'y', None)
>>> instance.a_class_method('x', 'y')
('x', 'y', None)

But the class is not usually intended to call the instance method, though it is expected to call the others:

>>> AClass.a_class_method('x', 'y')
('x', 'y', None)
>>> AClass.a_static_method('x', 'y')
('x', 'y', None)
>>> AClass.an_instance_method('x', 'y')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: an_instance_method() missing 1 required positional argument: 'y'

You would have to explicitly pass the instance to call the instance method:

>>> AClass.an_instance_method(instance, 'x', 'y')
('x', 'y', None)
  • "this is a static method in Python. It is merely attached for convenience to the class object. It could optionally be a separate function in another module, but its call signature would be the same." Seems more confusing than convenient. Why would you attach a function to a class if its body will have no notion of that class. – Lightness Races in Orbit Dec 29 '15 at 15:16
  • @LightnessRacesinOrbit I've elaborated on each point – Aaron Hall Dec 29 '15 at 15:30
  • Personally, the way I've always looked at it is that an instance method is an operation on a particular instance, a class method is a sort of constructor (for convenience, nothing like MyClass(1,2,3) but instead like, MyClass.get_special(1,2,3)), and a static method as just being a normal function that could stand alone anyway. – Zizouz212 Dec 29 '15 at 22:00
  • Yes, classmethods are typically used for alternative constructors (see my dict.fromkeys example above, see also the pandas.DataFrame source code), but that is not a defining characteristic. I sometimes merely need to access data stored at the class level from a method, without accessing the instance. If you're calling type(self) (or worse, self.__class__) and not otherwise using self directly in an instance method, that's a good sign that you should consider it to be a classmethod. As classmethods don't require instances, it makes them easier to unittest. – Aaron Hall Dec 29 '15 at 22:06
4
  • An "instance method" is a method that gets passed the instance object as its first parameter, which by convention is called self. This is the default.

  • A "static method" is a method without the initial self parameter. This is implemented with the @staticmethod decorator.

  • A "class method" is a method where the initial parameter is not an instance object, but the class object (see this part of the Python docs for what a "class object" is), which by convention is called cls. This is implemented with the @classmethod decorator.

The typical usage of the term "static method" in C/C++/etc applies to both Python "static" and Python "class" methods, since both of those types of methods lack a reference to the instance. In C/C++/etc, methods normally have implicit access to all non-instance members/methods of the class, which is probably why this distinction only exists in languages like Python/Ruby/etc.

  • Does a static method in C/C++ have a reference to the class object? Or just "members" of the class? Can they create new members of the class? :) – Aaron Hall Dec 29 '15 at 16:37
  • 3
    @AaronHall In C/C++, there is no such thing as a class object, and you don't need a reference to it to call static methods. You just write Class::staticMethod() and that's it (as long as you aren't forbidden from calling it because staticMethod() is private or something). – Ixrec Dec 29 '15 at 16:40

protected by gnat Aug 15 '16 at 23:49

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.