# What are Class Variables in Python OOP?

%[https://youtu.be/F7za_-e8UAw] 

### Introduction

In Python, class variables (also known as class attributes) **are shared across all instances (objects) of a class**. They belong to the class itself, not to any specific instance.

### The Problem: Why do we need Class Variables?

Consider the following code snippet:

```python
#We have a class "InefficientUser" defined with some basic data

class InefficientUser:
    def __init__(self, username):    
        self.username = username        
        self.max_login_attempts = 5 
        self.password_min_length = 8

# Creating two different user instances from this class:

u1 = InefficientUser("Shameel")
u2 = InefficientUser("Ammad")
```

In this class, the instance variables `max_login_attempts` and `password_min_length` are the values which are common and needs to be shared across all instances, whereas the username has to be a unique value for all instances.

Now, suppose for some reason, I want to change the value of `max_login_attempts` from 8 to 10 for the whole system. In such a case, I will have to manually change the value of `max_login_attempts` to 10 for every single instance, like this:

```python
u1.max_login_attempts = 10
u2.max_login_attempts = 10
```

The aforementioned method of modifying values might for work less number of instances, but consider your code having 100 instances from a class, and manually changing the value of a common variable in all of them? That would be a headache! So this method is Tedious, time-consuming, and error-prone as well.

This is where the "**Class Variables**" kick in with their magic! ✨

### The Solution: Class Variables to the rescue!

Class variables (also called class attributes) are variables that are defined inside a class but outside any instance methods or the `__init__` constructor. They hold data that is shared universally by all instances of that class, rather than data unique to each individual object. You may imagine them as global or shared data variables.

Consider the following code snippet:

```python
# We have a class "User" defined with some basic data. But this time, some variables are defined outside the __init__ method. These variables are "Class Variables".

class User:
    # Class Variables 
    max_login_attempts = 5 
    password_min_length = 8
    system_name = "hasabTech Portal"
    
    def __init__(self, username):  
        # Instance Variable  
        self.username = username        
        

# Creating two different user instances from this class:

user1 = User("Shameel")
user2 = User("Ammad")
```

In this code, the `User` class has 3 Class variables:

1.  `max_login_attempts`
    
2.  `password_min_length`
    
3.  `system_name`
    

These are shared variables and are attached to every instance that will be created from the `User` class. For example, the `user1` instance will have following properties and values:

![](https://cdn.hashnode.com/uploads/covers/688d0e1def7e30d5c07b0040/1104c473-1d0d-495c-990b-7967019921aa.png align="center")

Similarly, the `user2` instance will have following properties and values:

![](https://cdn.hashnode.com/uploads/covers/688d0e1def7e30d5c07b0040/7cb25e83-4bc4-4ece-b0ad-8b6ba561f186.png align="center")

So, we do not have to define these 3 properties and values again and again for each instance. And if we want to *modify* the value of any of these variables, we will just make changes in the value of the class variable defined inside the class, and all other instances will inherit the new value themselves.

### Main Use Cases of using Class Variables:

Since Class variables store data on the class level, here are some common use cases for which these variables are being used:

1.  **Sharing Constant or Configuration Values**: Storing data that should remain uniform across all instances, such as a company name, a default tax rate, or an API version.
    
2.  **Tracking Class-Wide State**: Keeping tabs on metrics that span across individual objects, such as a counter tracking the total number of objects created.
    
3.  **Defining Default Values**: Setting baseline attributes that every new object inherits automatically but can optionally override later.
    
4.  **Memory Efficiency**: Saving memory by maintaining a single copy of a variable instead of duplicating it inside every object.
    

### Accessing the values of Class Variables

There are two ways in which we can access the values of a Class variable.

1.  **Access value by class name**
    

*Accessing the value by class name* means that you access the value using the `Class.classVariableName` pattern.

For example, consider the same `User` class:

```python
class User:
    # Class Variables 
    max_login_attempts = 5 
    password_min_length = 8
    system_name = "hasabTech Portal"
    
    def __init__(self, username):  
        # Instance Variable  
        self.username = username               

# Print the value of all class variables using class name:

print(f"Max Login Attempts: {User.max_login_attempts}")
print(f"Minimum Password Length: {User.password_min_length}")
print(f"System Name: {User.system_name}")
```

1.  **Access value by instance name**
    

*Accessing the value by instance name* means that you access the value using the `instance.classVariableName` pattern.

For example, consider the same `User` class and it's instances `user1` and `user2`:

```python
class User:
    # Class Variables 
    max_login_attempts = 5 
    password_min_length = 8
    system_name = "hasabTech Portal"
    
    def __init__(self, username):  
        # Instance Variable  
        self.username = username     

# Creating two different user instances from this class:

user1 = User("Shameel")
user2 = User("Ammad")   
      

# Print the value of all class variables using user1 instance:
print(f"User 1 Max Login Attempts: {user1.max_login_attempts}")
print(f"User 1 Min Pass Length: {user1.password_min_length}")
print(f"User 1 System Name: {user1.system_name}")

# Print the value of all class variables using user2 instance:
print(f"User 2 Max Login Attempts: {user2.max_login_attempts}")
print(f"User 2  Min Pass Length: {user2.password_min_length}")
print(f"User 2 System Name: {user2.system_name}")
```

In the case of an instance variable, you are bound to access it using the instance name. However, in case of accessing class variables, it's a matter of choice how one wants to access a class variable. As a general rule of thumb, it is preferred to use pattern # 1 i.e., access class variable using Class name.

### Summary

**✅ What are Class Variables?**

Class variables (also known as class attributes) **are shared across all instances (objects) of a class**. They belong to the class itself, not to any specific instance.

**✅ Two ways of accessing the values of a Class Variable:**

1.  Access by Class name: `Class.classVariableName`
    
2.  Access by Instance name: `Instance.classVariableName`
    

***Stay connected with hasabTech for more information:***

[**Website**](https://hasab.tech/) [**| Facebook**](https://www.facebook.com/hasabTech) [**| LinkedIn**](https://www.linkedin.com/company/hasabtech) [**| YouTube**](https://youtube.com/@hasabTech) [**| X (Twitter)**](https://x.com/hasabTech) [**| TikTok**](https://tiktok.com/@hasabTech)
