Python's Instance, Class, and Static Methods Demystified
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
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:
NOTE: For Python 2 users: The @staticmethod and @classmethod decorators are available as of Python 2.4 and this example will work as is. Instead of using a plain class MyClass: declaration you might choose to declare a new-style class inheriting from object with the class MyClass(object): syntax. Other than that you’re good to go.
Instance Methods
The first method on MyClass , called method , 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, self , which points to an instance of MyClass when the method is called (but of course instance methods can accept more than just one parameter).
Through the self 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 self.__class__ attribute. This means instance methods can also modify class state.
Class Methods
Let’s compare that to the second method, MyClass.classmethod . I marked this method with a @classmethod decorator to flag it as a class method.
Instead of accepting a self parameter, class methods take a cls 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 cls argument, it can’t modify object instance state. That would require access to self . However, class methods can still modify class state that applies across all instances of the class.
Static Methods
The third method, MyClass.staticmethod was marked with a @staticmethod decorator to flag it as a static method.
This type of method takes neither a self nor a cls 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.
MyClass 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:
This confirmed that method (the instance method) has access to the object instance (printed as <MyClass instance> ) via the self argument.
When the method is called, Python replaces the self argument with the instance object, obj . We could ignore the syntactic sugar of the dot-call syntax ( obj.method() ) and pass the instance object manually to get the same result:
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 self.__class__ 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:
Calling classmethod() showed us it doesn’t have access to the <MyClass instance> object, but only to the <class MyClass> 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 MyClass.classmethod() . Calling a method in Python through the dot syntax triggers this behavior. The self parameter on instance methods works the same way.
Please note that naming these parameters self and cls is just a convention. You could just as easily name them the_object and the_class 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:
Did you see how we called staticmethod() 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 self or the cls 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:
We were able to call classmethod() and staticmethod() just fine, but attempting to call the instance method method() failed with a TypeError .
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 self 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 Pizza class:
Note: This code example and the ones further along in the tutorial use Python 3.6 f-strings to construct the string returned by __repr__ . On Python 2 and versions of Python 3 before 3.6 you’d use a different string formatting expression, for example:
Delicious Pizza Factories With @classmethod
If you’ve had any exposure to pizza in the real world you’ll know that there are many delicious variations available:
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 Pizza 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:
Note how I’m using the cls argument in the margherita and prosciutto factory methods instead of calling the Pizza 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:
As you can see, we can use the factory functions to create new Pizza objects that are configured the way we want them. They all use the same __init__ 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 __init__ 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:
Now what did I change here? First, I modified the constructor and __repr__ to accept an extra radius argument.
I also added an area() instance method that calculates and returns the pizza’s area (this would also be a good candidate for an @property — but hey, this is just a toy example).
Instead of calculating the area directly within area() , using the well-known circle area formula, I factored that out to a separate circle_area() static method.
Let’s try it out!
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 cls or self 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 circle_area() 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 circle_area() 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.
Key Takeaways
- Instance methods need a class instance and can access the instance through self .
- Class methods don’t need a class instance. They can’t access the instance ( self ) but they have access to the class itself via cls .
- Static methods don’t have access to cls or self . 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.
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
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.

About Dan Bader
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.
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:
11. Methods and @property¶
In this chapter, we will understand the usage of ‘methods’, ‘@property’ and ‘descriptor’.
11.2. Methods, staticmethod and classmethod¶
In previous chapters, we saw the examples of methods, e.g. ‘area’ and ‘cost’ in Listing 10.1 , inside the class without any decorator with them. The ‘decorators’ adds the additional functionality to the methods, and will be discussed in details in Chapter 12 .
In this section, we will quickly review the different types of methods with an example. Then these methods will be used with our previous examples.
In the below code, two decorators are used with the methods inside the class i.e. ‘staticmethod’ and ‘classmethod’. Please see the comments and notice: how do the different methods use different values of x for adding two numbers,
We can observe the following differences in these three methods from the below code,
- method : it uses the instance variable (self.x) for addition, which is set by __init__ function.
- classmethod : it uses class variable for addition.
- staticmethod : it uses the value of x which is defined in main program (i.e. outside the class ). If x = 20 is not defined, then NameError will be generated.
Below is the output for above code,
11.3. Research organization¶
In previous chapter, we had two users who are modifying the class attributes. First was the mathematician (mathematician.py), who is modifying the ‘radius’ in Listing 10.4 . And other is the box company, who were modifying the method ‘perimeter’ in Listing 10.5 . Lastly, we had a contributor who is creating a ‘table formatter’ in Listing 10.9 for displaying the output nicely.
If we change the the ‘radius’ to ‘diameter’ in the __init__ function of class Ring, then we need to modify the ‘area’ and ‘cost’ methods as well. Also, the codes of other users (mathematician and box company) will break. But we can solve this problem using ‘classmethod’ as shown next.
11.3.1. Multiple constructor using ‘classmethod’¶
The ‘classmethod’ is a very useful tools to create the multiple constructor as shown in the below listing.
Following are the outputs for above code,
11.3.2. Additional methods using ‘staticmethod’¶
Now, the research organization wants one more features in the class, i.e. Meter to Centimeter conversion. Note that this feature has no relation with the other methods in the class. In the other words, the output of Meter to Centimeter conversion will not be used anywhere in the class, but it’s handy for the organization to have this feature in the package. In such cases, we can use static methods.
There is no point to create a ‘meter_cm’ method as ‘meter_cm(self, meter)’ and store it in the dictionary, as we are not going to use it anywhere in the class. We added this to meet the client’s requirement only, hence it should be added as simple definition (not as methods), which can be done using @staticmethod. In the other words, static methods are used to attached functions to classes.
Following is the output of above code,
11.4. Micro-managing¶
Micro-managing is the method, where client tells us the ways in which the logic should be implemented. Lets understand it by an example.
Now the research organization wants that the ‘area’ should be calculated based on the ‘perimeter’. More specifically, they will provide the ‘diameter’, then we need to calculate the ‘perimeter’; then based on the ‘perimeter’, calculate the ‘radius’. And finally calculate the ‘area’ based on this new radius. This may look silly, but if we look closely, the radius will change slightly during this conversion process; as there will be some difference between (diameter/2) and (math.pi*diameter)/( 2*math.pi). The reason for difference is: on computer we do not cancel the math.pi at numerator with math.pi at denominator, but solve the numerator first and then divide by the denominator, and hence get some rounding errors.
11.4.1. Wrong Solution¶
The solution to this problem may look pretty simple, i.e. modify the ‘area’ method in the following way,
- If we run the above code, we will have the following results, which is exactly right.
Above solution looks pretty simple, but it will break the code in ‘box.py in Listing 10.5 ’, as it is modifying the perimeter by a factor of 2.0 by overriding the perimeter method. Therefore, for calculating the area in box.py file, python interpretor will use the child class method ‘perimeter’ for getting the value of perimeter. Hence, the area will be calculated based on the ‘modified parameter’, not based on actual parameter.
- In box.py, the area will be wrongly calculated, because it is modifying the perimeter for their usage. Now, radius will be calculated by new perimeter (as they override the perimeter method) and finally area will be modified due to change in radius values, as shown below,
11.4.2. Correct solution¶
The above problem can be resolved by creating a local copy of perimeter in the class. In this way, the child class method can not override the local-copy of parent class method. For this, we need to modify the code as below,
Below is the result for above listing,
Now, we will get the correct results for the ‘box.py’ as well, as shown below,
11.5. Private attributes are not for privatizing the attributes¶
In Section 10.7 , we saw that there is no concept of data-hiding in Python; and the attributes can be directly accessed by the the clients.
There is a misconception that the double underscore (‘__’) are used for data hiding in Python. In this section, we will see the correct usage of ‘__’ in Python.
11.5.1. Same local copy in child and parent class¶
In previous section, we made a local copy of method ‘perimeter’ as ‘_perimeter’. In this way, we resolve the problem of overriding the parent class method.
But, if the child class (i.e. box.py) makes a local copy the perimeter as well with the same name i.e. _perimeter, then we will again have the same problem, as shown below,
Now, we will have same problem as before,
11.5.2. Use ‘__perimeter’ instead of ‘_perimeter’ to solve the problem¶
The above problem can be solved using double underscore before the perimeter instead of one underscore, as shown below,
- First replace the _perimeter with __ perimeter in the ‘pythonic.py’ as below,
- Next replace the _perimeter with __ perimeter in the ‘box.py’ as below,
_ _ is not designed for making the attribute private, but for renaming the attribute with class name to avoid conflicts due to same name as we see in above example, where using same name i.e. _perimeter in both parent and child class resulted in the wrong answer.
If we use _ _perimeter instead of _perimeter, then _ _perimeter will be renamed as _ClassName__perimeter. Therefore, even parent and child class uses the same name with two underscore, the actual name will be differed because python interpretor will add the ClassName before those names, which will make it different from each other.
- Now, we have same name in both the files i.e. __perimeter, but problem will no longer occur as the ‘class-names’ will be added by the Python before __perimeter. Below is the result for both the python files,
There is no notion of private attributes in Python. All the objects are exposed to users. * But, single underscore before the method or variable indicates that the attribute should not be access directly. * _ _ is designed for freedom not for privacy as we saw in this section.
11.6. @property¶
Now, we will see the usage of @property in Python.
11.6.1. Managing attributes¶
Currently, we are not checking the correct types of inputs in our design. Let’s see our ‘pythonic.py’ file again.
Note that in the above code, the string is saved in the radius; and the multiplication is performed on the string. We do not want this behavior, therefore we need to perform some checks before saving data in the dictionary, which can be done using @property, as shown below,
- @property decorator allows . operator to call the function. Here, self.radius will call the method radius, which returns the self._radius. Hence, _radius is stored in the dictionary instead of dict.
- If we use ‘return self.radius’ instead of ‘return self._radius’, then the @property will result in infinite loop as self.property will call the property method, which will return self.property, which results in calling the @property again.
- Further, we can use @property for type checking, validation or performing various operations by writing codes in the setter method e.g. change the date to todays date etc.
- Below is the results for above code,
- Below is the dictionary of the object ‘r’ of code. Note that, the ‘radius’ does not exist there anymore, but this will not break the codes of other users, due to following reason.
@property is used to convert the attribute access to method access.
In the other words, the radius will be removed from instance variable list after defining the ‘property’ as in above code. Now, it can not be used anymore. But, @property decorator will convert the attribute access to method access, i.e. the dot operator will check for methods with @property as well. In this way, the code of other user will not break.
11.6.2. Calling method as attribute¶
If a method is decorated with @property then it can be called as ‘attribute’ using operator, but then it can not be called as attribute, as shown in below example,
11.6.3. Requirement from research organization¶
Now, we get another rule from the research organization as below,
- we do not want to store radius as instance variable,
- instead convert radius into diameter and save it as instance variable in the dictionary.
This condition will raise following two problems,
- Main problem here is that, other users already started using this class and have access to attribute ‘radius’. Now, if we replace the key ‘radius’ with ‘diameter’, then their code will break immediately.
- Also, we need to update all our code as everything is calculated based on radius; and we are going to remove these attribute from diameter.
This is the main reason for hiding attributes in java and c++, as these languages have no easy solution for this. Hence, these languages use getter and setter method.
But in python this problem can be solved using @property. @property is used to convert the attribute access to method access.
Python classmethod()

Python classmethod() is a built-in function of the Python standard library!
There are three types of methods in Python:
- Instance Method
- Class Method
Here, in this article, we’re going to discuss and focus on the class method of Python. So let’s get started.
What is a Python classmethod()?
A Python classmethod() can be called by a class as well as by an object. A method that returns a class method for a given function is called a classmethod().
It is a method that is shared among all objects. It is an in-built function in the Python programming language.
A classmethod() takes only one single parameter called function. Hence, the syntax of the classmethod() method in python is as follows:
Using the Python classmethod()
Let’s take a look at an example of the Python classmethod() function here. In the below example, we use the classmethod() function to print the marks of the student that are declared within the class instead of passing the variable to the function.
In the above code, we observe that:
- We have a class Student with member variable marks.
- We have a function printMarks which accepts parameter cls.
- We have passed the classmethod() that is always attached to a class.
- Here, the first argument is always a class itself which is why we use ‘cls’ when we define the class.
- Then we pass the method Student.printMarks as an argument to classmethod( ). The finally printMarks is called that prints the class variable marks.
Using the Decorator @classmethod
Another method to use the classmethod( ) function is by using the @classmethod Decorator.
Instead of the object, by using the decorator method we can call the class name. It can be applied to any method of the class.
The syntax of the @classmethod Decorator method is as follows: It takes one parameter and multiple arguments.
Let’s see how we can run a similar example with the use of the decoartor classmethod instead of using the function as in the previous example.
In the example mentioned above, the @classmethod decorator has applied to the printCourse( ) method. It has one parameter cls. The method then automatically picks the member variable of the class instead of requiring the user to pass one to the function.
Conclusion
This was in brief about the two ways in which you can use the Python classmethod( ) function. Stay tuned for more articles on Python!
@classmethod
Представляет функцию function методом класса. В метод класса первым аргументом неявным образом передаётся класс. Аналогично метод экземпляра получает в первом аргументе сам экземпляр.
Параметры ¶
Функция @classmethod принимает один параметр:
- function — функция, которую необходимо преобразовать в метод класса.
Возвращаемое значение ¶
Функция @classmethod возвращает метод класса для данной функции.
Примеры ¶
Для удобного объявления метода класса используйте @classmethod в виде декоратора:
Из примеров выше видно, что метод может вызываться как через класс MyClass.method() , так и через экземпляр MyClass().method() . При вызове метода из наследника в первом аргументе метод получит класс наследника.
Мы используем файлы cookie
Наш сайт использует файлы cookie для улучшения пользовательского опыта, сбора статистики и обеспечения доступа к обучающим материалам. Мы также передаем информацию об использовании вами нашего сайт партерам по социальным сетям, рекламе и аналитике. В свою очередь, наши партнеры могут объединять ее с другой предоставленной вами информацией, или с информацией, которую они собрали в результате использования вами их услуг.