Class & Instance Attributes in Python

In Python Programming Language, Class and Instance are two of object orientation's most crucial ideas. Instances are unique objects made in accordance with the class, whereas classes are templates. The procedure is the same for all objects, although the data may vary.

In this tutorial, we will learn about classes in python, how to instantiate them, what attributes are, and the differences between class and instance attribute in Python. Let’s begin with definitions –

What is a Class?

Classes provide a means of bundling data and functionality together in python. Creating a new class creates a new type of object, allowing new instances of that type to be made. Each class instance in python can have attributes attached to it for maintaining its state. Class instances can also have methods (defined by its class) for modifying its state.

What is an Instance?

Object or Instance

Python is an object-oriented programming language that stresses on objects, i.e., it mainly emphasizes functions. Objects are basically an encapsulation of data variables and methods acting on that data into a single entity in python. Almost everything in Python is an object, with its properties and methods. Even when you run “x = 5”, you are essentially creating an object from class ‘int’.

Python Class Attribute is an attribute/variable that is enclosed within a Class. That is, its scope lies within the Python class.

The Class attribute in python creates only a single copy of itself and this single copy is shared and utilized by all the functions and objects within that particular class.


class ClassName:
   some_string = 'test'  # this is a class attribute

It will be same for all instances of this class. Let’s create two objects from it and see the output.


o1 = ClassName() o2 = ClassName() print(ClassName.some_string) print(o1.some_string) print(o2.some_string)


# test
# test
# test

As clearly observed, a class attribute is shared across all objects created from it. Also, class attributes can be accessed by class_name.attribute_name as well as object.attribute_name. The attribute value can be changed as well by using class_name.attribute_name = 'new value'.

Python Instance attribute is a local attribute/variable whose scope lies within the particular function that is using the attribute.

The Instance attribute creates a new copy of itself, each time an object is created. The most common function used to achieve this behaviour is the __init__() method.


class SomeClass:
    def __init__(self, attr1, attr2):
        self.attr1 = attr1
        self.attr2 = attr2

Any number of attributes can be passed to the constructor. The way each object gets their own attributes can be understood like ‘self’ is referencing the object at creation time, so ‘self’ can never be accessed directly from the class.


obj1 = SomeClass('test', 10) obj2 = SomeClass('hello', 15) print(obj1.attr1, obj1.attr2) print(obj2.attr1, obj2.attr2)


# test 10
# hello 15

Here we can see each object has their own attribute values and only the object themselves have access to them.

So changing an attribute for one object will not affect other objects.

Instance attributes are accessed with the same dot (.) notation as class attributes. They can be changed or reassigned by using object_name.attribute_name = 'new value'.

Changing Class Attribute values

It may be tempting to change them the same way we change instance attributes, after all why not? One word, Inheritance.

Let’s take an example where we define a function that multiplies the class attribute’s value by 5 each time it’s called.


class ClassA: some_string = 'test' # this is a class attribute class_val = 2 # this is also a class attribute def update(self): ClassA.class_val *= 5 o1 = ClassA() o2 = ClassA() o1.update() print(ClassA.class_val) o2.update() print(ClassA.class_val)


# 10
# 50

Now let’s create a new class which inherits from this class.


class ClassB(ClassA): pass new_obj = ClassB() print(ClassA.class_val, ClassB.class_val) new_obj.update() print(ClassA.class_val, ClassB.class_val)


# 50 50
# 250 250

Why can a new class object change its parent class’ attributes along with its own? And more importantly how do you fix it?

There are two main issues with what we wrote −

  • ‘pass’ keyword in the definition of ClassB

  • The following piece of code −

def update(self):
    ClassA.class_val *= 5

Simply putting ‘pass’ means ClassB does not have its own attributes it simply points to its parent class. And secondly, we hardcoded the class name due to our temptation.

Also, calling this function will require an object to be created first as it expects a ‘self’ reference. Instead we can use something called a “Class Method”, which has a decorator of the same name. Here’s how it should look −

    def update(cls):
        cls.class_val *= 5

It basically says that we want to change the attribute of that specific class only from which it was called. Let’s take an example to make things more clear.

Finally, our two classes should look as follows −


class OldClass: some_string = 'test' # this is a class attribute class_val = 2 # this is also a class attribute @classmethod def update(cls): cls.class_val *= 5 class NewClass(OldClass): class_val = 2 # this is different from the parent class

Now time to call the update function from both classes separately.

print("Initially:", OldClass.class_val, NewClass.class_val) OldClass.update() print("After calling update on old class once:", OldClass.class_val, NewClass.class_val) NewClass.update() NewClass.update() print("After calling update on new class twice:", OldClass.class_val, NewClass.class_val)


# Initially: 2 2
# After calling update on old class once: 10 2
# After calling update on new class twice: 10 50

So, now we can change class attributes in python without creating objects, and even after inheriting from a parent class, the class methods will aware which class’ attributes are to be changed.