Do static methods belong to the class?

In Unit 2, we explored the Math class and its many static methods like Math.random(), and we’ve always used a main method which is static. In this lesson, you will learn to write your own static variables and methods.

  • Static variables and methods belong to a class and are called with the Class Name rather than using object variables, like ClassName.methodName();

  • There is only one copy of a static variable or method for the whole class. For example, the main method is static because there should only be 1 main method.

  • Static methods can be public or private.

  • The static keyword is placed right after the public/private modifier and right before the type of variables and methods in their declarations.

class ClassName {
  // static variable
  public static type variableName;

  // static method
  public static returnType methodName(parameters) {
        // implementation not shown
  }
}
// To call a static method or variable, use the Class Name
System.out.println(ClassName.staticVariable);
ClassName.staticMethod();

Static methods only have access to other static variables and static methods. Static methods cannot access or change the values of instance variables, but they can access or change the values of static variables.

The methods that belong to a class definition are called static methods. (Sometimes they are called class methods, but this is confusing.) A static method is part of a class definition, but is not part of the objects it creates.

Important: A program can execute a static method without first creating an object! All other methods (those that are not static) exist only when they are part of an object. So an object must be created before they can be executed.

The example application is similar to many you have seen so far. Let us look at what is going on. Assume that the source code is in a file named StringTester.java.

  • The file defines a class called StringTester.
  • The class has a static method called main().
  • Since main() is a static method, it is a characteristic of the class. Objects of the class do not have a main() method.
  • Since main() is a static method, there will be only one main() method.

  • The main() method can be run without an object.
  • After the file has been compiled, the resulting bytecodes are executed by the Java virtual machine.
    • The user executes the program by typing java StringTester (or clicking on a button in a programming environment.).
  • The Java virtual machine looks into the bytecode version of the class definition for the main() method.
    • No object exists at this point.
  • The main() method starts running, creates a StringTester.java2 object using StringTester.java3, invokes its StringTester.java4 method, and continues.

Remember the idea of object-oriented programming: an application consists of a collection of cooperating software objects whose methods are executed in a particular order to get something useful done. The steps listed above is how the collection of objects gets started. (In this case only one object was created.)

In this tutorial I’ll help demystify what’s behind class methods, static methods, and regular instance methods.

If you develop an intuitive understanding for their differences you’ll be able to write object-oriented Python that communicates its intent more clearly and will be easier to maintain in the long run.

Free Bonus: Click here to get access to a free Python OOP Cheat Sheet that points you to the best tutorials, videos, and books to learn more about Object-Oriented Programming with Python.

Instance, Class, and Static Methods — An Overview

Let’s begin by writing a (Python 3) class that contains simple examples for all three method types:

class MyClass:
    def method(self):
        return 'instance method called', self

    @classmethod
    def classmethod(cls):
        return 'class method called', cls

    @staticmethod
    def staticmethod():
        return 'static method called'

NOTE: For Python 2 users: The

>>> obj = MyClass()
>>> obj.method()
('instance method called', <MyClass instance at 0x10205d190>)
4 and
>>> obj = MyClass()
>>> obj.method()
('instance method called', <MyClass instance at 0x10205d190>)
5 decorators are available as of Python 2.4 and this example will work as is. Instead of using a plain
>>> obj = MyClass()
>>> obj.method()
('instance method called', <MyClass instance at 0x10205d190>)
6 declaration you might choose to declare a new-style class inheriting from
>>> obj = MyClass()
>>> obj.method()
('instance method called', <MyClass instance at 0x10205d190>)
7 with the
>>> obj = MyClass()
>>> obj.method()
('instance method called', <MyClass instance at 0x10205d190>)
8 syntax. Other than that you’re good to go.

Remove ads

Instance Methods

The first method on

>>> obj = MyClass()
>>> obj.method()
('instance method called', <MyClass instance at 0x10205d190>)
9, called
>>> MyClass.method(obj)
('instance method called', <MyClass instance at 0x10205d190>)
0, is a regular instance method. That’s the basic, no-frills method type you’ll use most of the time. You can see the method takes one parameter,
>>> MyClass.method(obj)
('instance method called', <MyClass instance at 0x10205d190>)
1, which points to an instance of
>>> obj = MyClass()
>>> obj.method()
('instance method called', <MyClass instance at 0x10205d190>)
9 when the method is called (but of course instance methods can accept more than just one parameter).

Through the

>>> MyClass.method(obj)
('instance method called', <MyClass instance at 0x10205d190>)
1 parameter, instance methods can freely access attributes and other methods on the same object. This gives them a lot of power when it comes to modifying an object’s state.

Not only can they modify object state, instance methods can also access the class itself through the

>>> MyClass.method(obj)
('instance method called', <MyClass instance at 0x10205d190>)
4 attribute. This means instance methods can also modify class state.

Class Methods

Let’s compare that to the second method,

>>> MyClass.method(obj)
('instance method called', <MyClass instance at 0x10205d190>)
5. I marked this method with a
>>> obj = MyClass()
>>> obj.method()
('instance method called', <MyClass instance at 0x10205d190>)
5 decorator to flag it as a class method.

Instead of accepting a

>>> MyClass.method(obj)
('instance method called', <MyClass instance at 0x10205d190>)
1 parameter, class methods take a
>>> MyClass.method(obj)
('instance method called', <MyClass instance at 0x10205d190>)
8 parameter that points to the class—and not the object instance—when the method is called.

Because the class method only has access to this

>>> MyClass.method(obj)
('instance method called', <MyClass instance at 0x10205d190>)
8 argument, it can’t modify object instance state. That would require access to
>>> MyClass.method(obj)
('instance method called', <MyClass instance at 0x10205d190>)
1. However, class methods can still modify class state that applies across all instances of the class.

Static Methods

The third method,

>>> obj.classmethod()
('class method called', <class MyClass at 0x101a2f4c8>)
1 was marked with a
>>> obj = MyClass()
>>> obj.method()
('instance method called', <MyClass instance at 0x10205d190>)
4 decorator to flag it as a static method.

This type of method takes neither a

>>> MyClass.method(obj)
('instance method called', <MyClass instance at 0x10205d190>)
1 nor a
>>> MyClass.method(obj)
('instance method called', <MyClass instance at 0x10205d190>)
8 parameter (but of course it’s free to accept an arbitrary number of other parameters).

Therefore a static method can neither modify object state nor class state. Static methods are restricted in what data they can access - and they’re primarily a way to namespace your methods.

Let’s See Them In Action!

I know this discussion has been fairly theoretical up to this point. And I believe it’s important that you develop an intuitive understanding for how these method types differ in practice. We’ll go over some concrete examples now.

Let’s take a look at how these methods behave in action when we call them. We’ll start by creating an instance of the class and then calling the three different methods on it.

>>> obj = MyClass()
>>> obj.method()
('instance method called', <MyClass instance at 0x10205d190>)
9 was set up in such a way that each method’s implementation returns a tuple containing information for us to trace what’s going on — and which parts of the class or object the method can access.

Here’s what happens when we call an instance method:

>>>

>>> obj = MyClass()
>>> obj.method()
('instance method called', <MyClass instance at 0x10205d190>)

This confirmed that

>>> MyClass.method(obj)
('instance method called', <MyClass instance at 0x10205d190>)
0 (the instance method) has access to the object instance (printed as
>>> obj.classmethod()
('class method called', <class MyClass at 0x101a2f4c8>)
7) via the
>>> MyClass.method(obj)
('instance method called', <MyClass instance at 0x10205d190>)
1 argument.

When the method is called, Python replaces the

>>> MyClass.method(obj)
('instance method called', <MyClass instance at 0x10205d190>)
1 argument with the instance object,
>>> obj.staticmethod()
'static method called'
0. We could ignore the syntactic sugar of the dot-call syntax (
>>> obj.staticmethod()
'static method called'
1) and pass the instance object manually to get the same result:

>>>

>>> MyClass.method(obj)
('instance method called', <MyClass instance at 0x10205d190>)

Can you guess what would happen if you tried to call the method without first creating an instance?

By the way, instance methods can also access the class itself through the

>>> MyClass.method(obj)
('instance method called', <MyClass instance at 0x10205d190>)
4 attribute. This makes instance methods powerful in terms of access restrictions - they can modify state on the object instance and on the class itself.

Let’s try out the class method next:

>>>

>>> obj.classmethod()
('class method called', <class MyClass at 0x101a2f4c8>)

Calling

>>> obj.staticmethod()
'static method called'
3 showed us it doesn’t have access to the
>>> obj.classmethod()
('class method called', <class MyClass at 0x101a2f4c8>)
7 object, but only to the
>>> obj.staticmethod()
'static method called'
5 object, representing the class itself (everything in Python is an object, even classes themselves).

Notice how Python automatically passes the class as the first argument to the function when we call

>>> obj.staticmethod()
'static method called'
6. Calling a method in Python through the dot syntax triggers this behavior. The
>>> MyClass.method(obj)
('instance method called', <MyClass instance at 0x10205d190>)
1 parameter on instance methods works the same way.

Please note that naming these parameters

>>> MyClass.method(obj)
('instance method called', <MyClass instance at 0x10205d190>)
1 and
>>> MyClass.method(obj)
('instance method called', <MyClass instance at 0x10205d190>)
8 is just a convention. You could just as easily name them
>>> MyClass.classmethod()
('class method called', <class MyClass at 0x101a2f4c8>)

>>> MyClass.staticmethod()
'static method called'

>>> MyClass.method()
TypeError: unbound method method() must
    be called with MyClass instance as first
    argument (got nothing instead)
0 and
>>> MyClass.classmethod()
('class method called', <class MyClass at 0x101a2f4c8>)

>>> MyClass.staticmethod()
'static method called'

>>> MyClass.method()
TypeError: unbound method method() must
    be called with MyClass instance as first
    argument (got nothing instead)
1 and get the same result. All that matters is that they’re positioned first in the parameter list for the method.

Time to call the static method now:

>>>

>>> obj.staticmethod()
'static method called'

Did you see how we called

>>> MyClass.classmethod()
('class method called', <class MyClass at 0x101a2f4c8>)

>>> MyClass.staticmethod()
'static method called'

>>> MyClass.method()
TypeError: unbound method method() must
    be called with MyClass instance as first
    argument (got nothing instead)
2 on the object and were able to do so successfully? Some developers are surprised when they learn that it’s possible to call a static method on an object instance.

Behind the scenes Python simply enforces the access restrictions by not passing in the

>>> MyClass.method(obj)
('instance method called', <MyClass instance at 0x10205d190>)
1 or the
>>> MyClass.method(obj)
('instance method called', <MyClass instance at 0x10205d190>)
8 argument when a static method gets called using the dot syntax.

This confirms that static methods can neither access the object instance state nor the class state. They work like regular functions but belong to the class’s (and every instance’s) namespace.

Now, let’s take a look at what happens when we attempt to call these methods on the class itself - without creating an object instance beforehand:

>>>

>>> MyClass.classmethod()
('class method called', <class MyClass at 0x101a2f4c8>)

>>> MyClass.staticmethod()
'static method called'

>>> MyClass.method()
TypeError: unbound method method() must
    be called with MyClass instance as first
    argument (got nothing instead)

We were able to call

>>> obj.staticmethod()
'static method called'
3 and
>>> MyClass.classmethod()
('class method called', <class MyClass at 0x101a2f4c8>)

>>> MyClass.staticmethod()
'static method called'

>>> MyClass.method()
TypeError: unbound method method() must
    be called with MyClass instance as first
    argument (got nothing instead)
2 just fine, but attempting to call the instance method
>>> MyClass.classmethod()
('class method called', <class MyClass at 0x101a2f4c8>)

>>> MyClass.staticmethod()
'static method called'

>>> MyClass.method()
TypeError: unbound method method() must
    be called with MyClass instance as first
    argument (got nothing instead)
7 failed with a
>>> MyClass.classmethod()
('class method called', <class MyClass at 0x101a2f4c8>)

>>> MyClass.staticmethod()
'static method called'

>>> MyClass.method()
TypeError: unbound method method() must
    be called with MyClass instance as first
    argument (got nothing instead)
8.

And this is to be expected — this time we didn’t create an object instance and tried calling an instance function directly on the class blueprint itself. This means there is no way for Python to populate the

>>> MyClass.method(obj)
('instance method called', <MyClass instance at 0x10205d190>)
1 argument and therefore the call fails.

This should make the distinction between these three method types a little more clear. But I’m not going to leave it at that. In the next two sections I’ll go over two slightly more realistic examples for when to use these special method types.

I will base my examples around this bare-bones

class Pizza:
    def __init__(self, ingredients):
        self.ingredients = ingredients

    def __repr__(self):
        return f'Pizza({self.ingredients!r})'
0 class:

class Pizza:
    def __init__(self, ingredients):
        self.ingredients = ingredients

    def __repr__(self):
        return f'Pizza({self.ingredients!r})'

>>>

>>> Pizza(['cheese', 'tomatoes'])
Pizza(['cheese', 'tomatoes'])

Note: This code example and the ones further along in the tutorial use Python 3.6 f-strings to construct the string returned by

class Pizza:
    def __init__(self, ingredients):
        self.ingredients = ingredients

    def __repr__(self):
        return f'Pizza({self.ingredients!r})'
1. On Python 2 and versions of Python 3 before 3.6 you’d use a different string formatting expression, for example:

def __repr__(self):
    return 'Pizza(%r)' % self.ingredients

Remove ads

Delicious Pizza Factories With >>> obj = MyClass() >>> obj.method() ('instance method called', <MyClass instance at 0x10205d190>) 5

If you’ve had any exposure to pizza in the real world you’ll know that there are many delicious variations available:

Pizza(['mozzarella', 'tomatoes'])
Pizza(['mozzarella', 'tomatoes', 'ham', 'mushrooms'])
Pizza(['mozzarella'] * 4)

The Italians figured out their pizza taxonomy centuries ago, and so these delicious types of pizzas all have their own names. We’d do well to take advantage of that and give the users of our

class Pizza:
    def __init__(self, ingredients):
        self.ingredients = ingredients

    def __repr__(self):
        return f'Pizza({self.ingredients!r})'
0 class a better interface for creating the pizza objects they crave.

A nice and clean way to do that is by using class methods as factory functions for the different kinds of pizzas we can create:

>>> obj = MyClass()
>>> obj.method()
('instance method called', <MyClass instance at 0x10205d190>)
0

Note how I’m using the

>>> MyClass.method(obj)
('instance method called', <MyClass instance at 0x10205d190>)
8 argument in the
class Pizza:
    def __init__(self, ingredients):
        self.ingredients = ingredients

    def __repr__(self):
        return f'Pizza({self.ingredients!r})'
5 and
class Pizza:
    def __init__(self, ingredients):
        self.ingredients = ingredients

    def __repr__(self):
        return f'Pizza({self.ingredients!r})'
6 factory methods instead of calling the
class Pizza:
    def __init__(self, ingredients):
        self.ingredients = ingredients

    def __repr__(self):
        return f'Pizza({self.ingredients!r})'
0 constructor directly.

This is a trick you can use to follow the Don’t Repeat Yourself (DRY) principle. If we decide to rename this class at some point we won’t have to remember updating the constructor name in all of the classmethod factory functions.

Now, what can we do with these factory methods? Let’s try them out:

>>>

>>> obj = MyClass()
>>> obj.method()
('instance method called', <MyClass instance at 0x10205d190>)
1

As you can see, we can use the factory functions to create new

class Pizza:
    def __init__(self, ingredients):
        self.ingredients = ingredients

    def __repr__(self):
        return f'Pizza({self.ingredients!r})'
0 objects that are configured the way we want them. They all use the same
class Pizza:
    def __init__(self, ingredients):
        self.ingredients = ingredients

    def __repr__(self):
        return f'Pizza({self.ingredients!r})'
9 constructor internally and simply provide a shortcut for remembering all of the various ingredients.

Another way to look at this use of class methods is that they allow you to define alternative constructors for your classes.

Python only allows one

class Pizza:
    def __init__(self, ingredients):
        self.ingredients = ingredients

    def __repr__(self):
        return f'Pizza({self.ingredients!r})'
9 method per class. Using class methods it’s possible to add as many alternative constructors as necessary. This can make the interface for your classes self-documenting (to a certain degree) and simplify their usage.

When To Use Static Methods

It’s a little more difficult to come up with a good example here. But tell you what, I’ll just keep stretching the pizza analogy thinner and thinner… (yum!)

Here’s what I came up with:

>>> obj = MyClass()
>>> obj.method()
('instance method called', <MyClass instance at 0x10205d190>)
2

Now what did I change here? First, I modified the constructor and

class Pizza:
    def __init__(self, ingredients):
        self.ingredients = ingredients

    def __repr__(self):
        return f'Pizza({self.ingredients!r})'
1 to accept an extra
>>> Pizza(['cheese', 'tomatoes'])
Pizza(['cheese', 'tomatoes'])
2 argument.

I also added an

>>> Pizza(['cheese', 'tomatoes'])
Pizza(['cheese', 'tomatoes'])
3 instance method that calculates and returns the pizza’s area (this would also be a good candidate for an
>>> Pizza(['cheese', 'tomatoes'])
Pizza(['cheese', 'tomatoes'])
4 — but hey, this is just a toy example).

Instead of calculating the area directly within

>>> Pizza(['cheese', 'tomatoes'])
Pizza(['cheese', 'tomatoes'])
3, using the well-known circle area formula, I factored that out to a separate
>>> Pizza(['cheese', 'tomatoes'])
Pizza(['cheese', 'tomatoes'])
6 static method.

Let’s try it out!

>>>

>>> obj = MyClass()
>>> obj.method()
('instance method called', <MyClass instance at 0x10205d190>)
3

Sure, this is a bit of a simplistic example, but it’ll do alright helping explain some of the benefits that static methods provide.

As we’ve learned, static methods can’t access class or instance state because they don’t take a

>>> MyClass.method(obj)
('instance method called', <MyClass instance at 0x10205d190>)
8 or
>>> MyClass.method(obj)
('instance method called', <MyClass instance at 0x10205d190>)
1 argument. That’s a big limitation — but it’s also a great signal to show that a particular method is independent from everything else around it.

In the above example, it’s clear that

>>> Pizza(['cheese', 'tomatoes'])
Pizza(['cheese', 'tomatoes'])
6 can’t modify the class or the class instance in any way. (Sure, you could always work around that with a global variable but that’s not the point here.)

Now, why is that useful?

Flagging a method as a static method is not just a hint that a method won’t modify class or instance state — this restriction is also enforced by the Python runtime.

Techniques like that allow you to communicate clearly about parts of your class architecture so that new development work is naturally guided to happen within these set boundaries. Of course, it would be easy enough to defy these restrictions. But in practice they often help avoid accidental modifications going against the original design.

Put differently, using static methods and class methods are ways to communicate developer intent while enforcing that intent enough to avoid most slip of the mind mistakes and bugs that would break the design.

Applied sparingly and when it makes sense, writing some of your methods that way can provide maintenance benefits and make it less likely that other developers use your classes incorrectly.

Static methods also have benefits when it comes to writing test code.

Because the

>>> Pizza(['cheese', 'tomatoes'])
Pizza(['cheese', 'tomatoes'])
6 method is completely independent from the rest of the class it’s much easier to test.

We don’t have to worry about setting up a complete class instance before we can test the method in a unit test. We can just fire away like we would testing a regular function. Again, this makes future maintenance easier.

Remove ads

Key Takeaways

  • Instance methods need a class instance and can access the instance through
    >>> MyClass.method(obj)
    ('instance method called', <MyClass instance at 0x10205d190>)
    
    1.
  • Class methods don’t need a class instance. They can’t access the instance (
    >>> MyClass.method(obj)
    ('instance method called', <MyClass instance at 0x10205d190>)
    
    1) but they have access to the class itself via
    >>> MyClass.method(obj)
    ('instance method called', <MyClass instance at 0x10205d190>)
    
    8.
  • Static methods don’t have access to
    >>> MyClass.method(obj)
    ('instance method called', <MyClass instance at 0x10205d190>)
    
    8 or
    >>> MyClass.method(obj)
    ('instance method called', <MyClass instance at 0x10205d190>)
    
    1. They work like regular functions but belong to the class’s namespace.
  • Static and class methods communicate and (to a certain degree) enforce developer intent about class design. This can have maintenance benefits.

Mark as Completed

Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: OOP Method Types in Python: @classmethod vs @staticmethod vs Instance Methods

🐍 Python Tricks 💌

Get a short & sweet Python Trick delivered to your inbox every couple of days. No spam ever. Unsubscribe any time. Curated by the Real Python team.

Do static methods belong to the class?

Send Me Python Tricks »

About Dan Bader

Do static methods belong to the class?
Do static methods belong to the class?

Dan Bader is the owner and editor in chief of Real Python and the main developer of the realpython.com learning platform. Dan has been writing code for more than 20 years and holds a master's degree in computer science.

» More about Dan


Each tutorial at Real Python is created by a team of developers so that it meets our high quality standards. The team members who worked on this tutorial are:

Do static methods belong to the class?

Aldren

Master Real-World Python Skills With Unlimited Access to Real Python

Do static methods belong to the class?

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

Master Real-World Python Skills
With Unlimited Access to Real Python

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

What Do You Think?

Rate this article:

Tweet Share Share Email

What’s your #1 takeaway or favorite thing you learned? How are you going to put your newfound skills to use? Leave a comment below and let us know.

Commenting Tips: The most useful comments are those written with the goal of learning from or helping out other students. Get tips for asking good questions and get answers to common questions in our support portal.


Looking for a real-time conversation? Visit the Real Python Community Chat or join the next “Office Hours” Live Q&A Session. Happy Pythoning!

Keep Learning

Related Tutorial Categories: intermediate python

Recommended Video Course: OOP Method Types in Python: @classmethod vs @staticmethod vs Instance Methods

Are static methods associated with the class?

Static method(s) are associated with the class in which they reside i.e. they are called without creating an instance of the class i.e ClassName. methodName(args). They are designed with the aim to be shared among all objects created from the same class.

Is a static method part of the object?

A static method (or static function) is a method defined as a member of an object but is accessible directly from an API object's constructor, rather than from an object instance created via the constructor.