Static variables

Published Aug. 6, 2023, 4:50 p.m.

Static variables are class-level variables that have the same value for all objects of the class. They are declared within the class but outside of methods. Unlike instance variables, static variables are shared among all instances of the class.

For total class only one copy of static variable will be created and shared by all objects of that class. 

We can access static variables either by class name or by object reference. But recommended to use class name.

class Test:
    x = 10  # Static variable

    def __init__(self):
        self.y = 20  # Instance variable

t1 = Test()
t2 = Test()

print('t1:', t1.x, t1.y)  # Output: t1: 10 20
print('t2:', t2.x, t2.y)  # Output: t2: 10 20

Test.x = 888
t1.y = 999

print('t1:', t1.x, t1.y)  # Output: t1: 888 999
print('t2:', t2.x, t2.y)  # Output: t2: 888 20

Output: 

t1: 10 20
t2: 10 20
t1: 888 999
t2: 888 20

Explanation:

We define a class named Test.

Inside the class, we declare a static variable x with a value of 10. Static variables are common to all instances of the class.

In the constructor (__init__), we define an instance variable y with a value of 20. This variable is specific to each instance of the class.

We create two instances, t1 and t2, of the Test class.

When we access t1.x and t2.x, we are accessing the static variable x. Since x is the same for all instances, both t1.x and t2.x have the value 10.

Similarly, when we access t1.y and t2.y, we are accessing the instance variable y. Since y is specific to each instance, t1.y is 20 and t2.y is 20.

We then change the value of Test.x to 888. This change affects both t1.x and t2.x, so they both have the value 888.

Next, we change the value of t1.y to 999. This change only affects the instance t1, so t1.y is 999 while t2.y remains 20.

In summary, static variables are shared among all instances of the class, while instance variables have separate values for each instance.

Different Spots to Set Static Variables:

  1. Class-Level Declaration: Static variables can be declared directly within the class, outside any methods. They're accessible across instances.

  2. Constructor Initialization: Inside the class's constructor, you can assign values to static variables using the class name. These values are initialized when an instance is created.

  3. Within Instance Methods: Inside instance methods, you can use the class name to work with static variables that are shared by all instances.

  4. In Class Methods: You can declare static variables within class methods. Access them using the class name or cls (which refers to the class itself).

  5. Within Static Methods: Even static methods can access static variables using the class name. You can use static methods for operations that involve the class as a whole.

# Define a class named Test
class Test:
    # Define a static variable 'a' with value 10
    a = 10

    # Define the constructor (__init__) for the class
    def __init__(self):
        # Set a static variable 'b' within the class
        Test.b = 20

    # Define an instance method 'm1'
    def m1(self):
        # Set a static variable 'c' within the class
        Test.c = 30

    # Define a class method 'm2'
    @classmethod
    def m2(cls):
        # Set a static variable 'd1' within the class using 'cls'
        cls.d1 = 40
        # Set a static variable 'd2' within the class using the class name
        Test.d2 = 400

    # Define a static method 'm3'
    @staticmethod
    def m3():
        # Set a static variable 'e' within the class
        Test.e = 50
        # Print the current dictionary of the class
        print(Test.__dict__)

# Print the dictionary of the Test class before any changes
print("Dictionary of Test class (before):", Test.__dict__)

# Create an instance of the Test class
t = Test()

# Print the dictionary of the Test class after the constructor
print("Dictionary of Test class (after constructor):", Test.__dict__)

# Call instance method 'm1'
t.m1()

# Print the dictionary of the Test class after calling 'm1'
print("Dictionary of Test class (after m1):", Test.__dict__)

# Call class method 'm2'
Test.m2()

# Print the dictionary of the Test class after calling 'm2'
print("Dictionary of Test class (after m2):", Test.__dict__)

# Call static method 'm3'
Test.m3()

# Print the dictionary of the Test class after calling 'm3'
print("Dictionary of Test class (after m3):", Test.__dict__)

# Add a static variable 'f' to the Test class
Test.f = 60

# Print the dictionary of the Test class after adding 'f'
print("Dictionary of Test class (after adding 'f'):", Test.__dict__)

Explanation:

This code demonstrates the process of adding and modifying static variables within a class, and it prints the class's dictionary (__dict__) at various points to show the changes.

  • At each step, the dictionary of the Test class is printed, showing the static variables present in the class's namespace.
  • The constructor __init__, instance method m1, class method m2, and static method m3 are used to add static variables to the class.
  • The dictionary is printed before and after each method call to illustrate how the class's dictionary changes.
  • Finally, a static variable f is added to the class, and the dictionary is printed again to show the final state of the class's namespace.

Accessing Static Variables in Python

Static variables are shared among all instances of a class and can be accessed in various ways. Here's how you can access static variables:

  1. Inside the Constructor:

    • Using self: Access the static variable using self and the class name.
    • Using Class Name: Directly access the static variable using the class name.
  2. Inside an Instance Method:

    • Using self: Access the static variable using self and the class name.
    • Using Class Name: Directly access the static variable using the class name.
  3. Inside a Class Method:

    • Using cls Variable: Access the static variable using cls and the class name.
    • Using Class Name: Directly access the static variable using the class name.
  4. Inside a Static Method:

    • Using Class Name: Directly access the static variable using the class name.
  5. From Outside the Class:

    • Using Object Reference: Access the static variable using the object reference.
    • Using Class Name: Directly access the static variable using the class name.

This approach offers flexibility in accessing static variables depending on the context, whether it's within methods, outside the class, or even within different types of methods.

# Define a class named Test
class Test:
    # Declare a static variable 'a' with value 10
    a = 10

    # Constructor
    def __init__(self):
        # Access 'a' using self and the class name
        print("Inside constructor:")
        print(self.a)   # Output: 10 (access via self)
        print(Test.a)   # Output: 10 (access via class name)

    # Instance method
    def m1(self):
        # Access 'a' using self and the class name
        print("\nInside instance method m1:")
        print(self.a)   # Output: 10 (access via self)
        print(Test.a)   # Output: 10 (access via class name)

    # Class method
    @classmethod
    def m2(cls):
        # Access 'a' using cls and the class name
        print("\nInside class method m2:")
        print(cls.a)    # Output: 10 (access via cls)
        print(Test.a)   # Output: 10 (access via class name)

    # Static method
    @staticmethod
    def m3():
        # Access 'a' using the class name
        print("\nInside static method m3:")
        print(Test.a)   # Output: 10 (access via class name)

# Create an instance of the Test class
t = Test()

# Access 'a' using the class name outside the class
print("\nOutside the class:")
print(Test.a)       # Output: 10 (access via class name)

# Access 'a' using the object reference outside the class
print(t.a)          # Output: 10 (access via object reference)

# Call instance method m1
t.m1()

# Call class method m2
t.m2()

# Call static method m3
t.m3()

Explanation:

  1. A class named Test is defined with a static variable a initialized to 10.

  2. Inside the constructor, instance method m1, class method m2, and static method m3, the static variable a is accessed using selfcls, or the class name Test. The output displays the value of a for each access method.

  3. An instance t of the Test class is created using the constructor.

  4. Outside the class, the static variable a is accessed both through the class name Test and through the instance reference t.

  5. Instance method m1 is called on the instance t, and it accesses the static variable a.

  6. Class method m2 is called on the instance t, and it accesses the static variable a.

  7. Static method m3 is called on the instance t, and it accesses the static variable a.

The code demonstrates how static variables can be accessed within different parts of the class and outside the class using both class names and instance references.

Modifying Static Variable Values

Static variables can be modified from various locations, both inside and outside the class. The primary method of modification is by using the class name. Additionally, within class methods, you can modify them using the cls variable.

  1. Anywhere within the Class or Outside: You can modify static variables from anywhere using the class name.

  2. Inside Class Methods using cls: Within class methods, you can modify static variables using the cls variable, which refers to the class itself.

This flexibility allows you to update static variable values to meet specific requirements while adhering to the appropriate scope.

Example:

# Define a class named Test
class Test:
    # Define a static variable 'a' with initial value 777
    a = 777

    # Class method to modify 'a' using 'cls'
    @classmethod
    def m1(cls):
        cls.a = 888

    # Static method to modify 'a'
    @staticmethod
    def m2():
        Test.a = 999
        print(Test.a)  # Output: 999

# Print initial value of 'a'
print(Test.a)  # Output: 777

# Call class method 'm1' to modify 'a'
Test.m1()

# Print value of 'a' after 'm1' call
print(Test.a)  # Output: 888

# Call static method 'm2' to modify 'a'
Test.m2()

# Print final value of 'a' after 'm2' call
print(Test.a)  # Output: 999

Output:

Initial value of 'a':
777

Value of 'a' after calling m1:
888

Value of 'a' after calling m2:
999

Final value of 'a':
999

Explanation:

  1. The class Test is defined with a static variable a initially set to 777.

  2. The class method m1 modifies the value of a using the cls variable (which refers to the class itself) and sets it to 888.

  3. The static method m2 modifies the value of a directly using the class name and sets it to 999. The method also prints the modified value.

  4. The initial value of a is printed (print(Test.a)) with an output of 777.

  5. The class method m1 is called, modifying the value of a to 888.

  6. The value of a after the class method call is printed, resulting in an output of 888.

  7. The static method m2 is called, modifying the value of a to 999. The method also prints the modified value (output: 999).

  8. The final value of a is printed after the static method call, resulting in an output of 999.

The code demonstrates how static variables can be modified within class methods and static methods, and the corresponding changes are shown in the output.

Changing Static Variable Values: Using self or Object Reference

Imagine you have a static variable in a class. If you try to change its value using self (within an instance method) or an object reference, something interesting happens:

What Happens: The value of the static variable won't actually change. Instead, a new variable specific to that object is created, which might seem like the static variable was updated.

In simple terms, modifying a static variable with self or object reference doesn't alter the original static value. It appears changed only because a new variable related to that particular object is created. To genuinely modify a static variable, use the class name or a class method.

Example 1:

# Define a class named Test
class Test:
    a = 10

    # Instance method m1
    def m1(self):
        self.a = 888

# Create an instance t1 of the Test class
t1 = Test()

# Call method m1 on t1
t1.m1()

# Output
print(Test.a)  # Output: 10
print(t1.a)    # Output: 888

Explanation:

  • The class Test has a static variable a with a value of 10.
  • An instance t1 of the Test class is created.
  • The instance method m1 modifies the value of a using self.
  • Even though t1.a appears to be modified, it's actually creating a new instance variable for t1, not modifying the static variable a.

Example 2:

# Define a class named Test
class Test:
    x = 10

    # Constructor
    def __init__(self):
        self.y = 20

# Create instances t1 and t2 of the Test class
t1 = Test()
t2 = Test()

# Output before modifications
print('t1:', t1.x, t1.y)  # Output: t1: 10 20
print('t2:', t2.x, t2.y)  # Output: t2: 10 20

# Modify variables for t1
t1.x = 888
t1.y = 999

# Output after modifications
print('t1:', t1.x, t1.y)  # Output: t1: 888 999
print('t2:', t2.x, t2.y)  # Output: t2: 10 20

Explanation:

  • The class Test has a static variable x with a value of 10 and an instance variable y initialized in the constructor.
  • Instances t1 and t2 of the Test class are created.
  • The output before modifications shows that t1 and t2 both have the same values for x and y.
  • Modifications to t1.x and t1.y create instance variables specific to t1, leaving t2 unaffected.

Example 3:

# Define a class named Test
class Test:
    a = 10

    # Constructor
    def __init__(self):
        self.b = 20

# Create instances t1 and t2 of the Test class
t1 = Test()
t2 = Test()

# Modify static and instance variables
Test.a = 888
t1.b = 999

# Output
print(t1.a, t1.b)   # Output: 888 999
print(t2.a, t2.b)   # Output: 888 20

Explanation:

  • The class Test has a static variable a with an initial value of 10 and an instance variable b initialized in the constructor.
  • Instances t1 and t2 of the Test class are created.
  • The static variable a is modified using the class name Test.
  • The instance variable b of t1 is modified.
  • As a result, t1.a and t1.b reflect the changes, while t2.a retains the change to a but maintains its original value of b.

Example 4:

# Define a class named Test
class Test:
    a = 10

    # Constructor
    def __init__(self):
        self.b = 20

    # Instance method m1
    def m1(self):
        self.a = 888
        self.b = 999

# Create instances t1 and t2 of the Test class
t1 = Test()
t2 = Test()

# Call method m1 on t1
t1.m1()

# Output
print(t1.a, t1.b)   # Output: 888 999
print(t2.a, t2.b)   # Output: 10 20

Explanation:

  • Similar to the previous example, the class Test has static variable a and instance variable b.
  • The instance method m1 modifies both the static variable a and the instance variable b using self.
  • After calling t1.m1()t1.a and t1.b are changed, while t2.a and t2.b remain unaffected.

Example 5:

# Define a class named Test
class Test:
    a = 10

    # Constructor
    def __init__(self):
        self.b = 20

    # Class method m1
    @classmethod
    def m1(cls):
        cls.a = 888
        cls.b = 999

# Create instances t1 and t2 of the Test class
t1 = Test()
t2 = Test()

# Call class method m1
t1.m1()

# Output
print(t1.a, t1.b)       # Output: 888 999
print(t2.a, t2.b)       # Output: 888 999
print(Test.a, Test.b)   # Output: 888 999

Explanation:

  • In this example, the class Test again has static variable a and instance variable b.
  • The class method m1 modifies both the static variable a and the instance variable b using the cls variable.
  • Calling t1.m1() updates the static and instance variables for both t1 and t2.

Deleting Static Variables in Python

Static variables of a class can be deleted using the del statement. The syntax is del classname.variablename. Additionally, within a class method, the cls variable can also be used for deletion: del cls.variablename.

Example 1:

# Define a class named Test
class Test:
    a = 10

    # Class method m1
    @classmethod
    def m1(cls):
        # Delete static variable 'a' using cls
        del cls.a

# Call class method m1
Test.m1()

# Output: {}
print(Test.__dict__)

Explanation:

  • The class Test has a static variable a initially set to 10.
  • In the class method m1, the static variable a is deleted using the del statement with the cls variable.
  • After calling Test.m1(), the static variable a is deleted, and the Test class dictionary becomes empty.

Example 2:

# Define a class named Test
class Test:
    a = 10

    # Constructor
    def __init__(self):
        Test.b = 20

    # Instance method m1
    def m1(self):
        Test.c = 30
        del Test.b

    # Class method m2
    @classmethod
    def m2(cls):
        cls.d = 40
        del Test.c

    # Static method m3
    @staticmethod
    def m3():
        Test.e = 50
        del Test.d

# Create an instance of the Test class
t = Test()

# Output: {'a': 10}
print(Test.__dict__)

# Call instance method m1
t.m1()

# Output: {'a': 10, 'c': 30}
print(Test.__dict__)

# Call class method m2
Test.m2()

# Output: {'a': 10, 'd': 40}
print(Test.__dict__)

# Call static method m3
Test.m3()

# Output: {'a': 10, 'e': 50}
print(Test.__dict__)

# Add static variable 'f'
Test.f = 60

# Output: {'a': 10, 'e': 50, 'f': 60}
print(Test.__dict__)

# Delete static variable 'e'
del Test.e

# Output: {'a': 10, 'f': 60}
print(Test.__dict__)

Explanation:

  • The class Test has a static variable a and methods m1m2, and m3.
  • Inside the constructor, the static variable b is added to the class.
  • In m1, the static variable c is added and b is deleted.
  • In m2, the class method adds the static variable d and deletes c.
  • In m3, the static method adds the static variable e and deletes d.
  • After each addition or deletion, the class dictionary (Test.__dict__) reflects the changes. Certainly! Here's the information with the added line:

Accessing and Modifying Static Variables with Object References

In Python, you can use object references or self to access static variables, but there are certain limitations:

  • Access: You can read the value of static variables using object references or self, similar to how you access instance variables.

  • Modification: If you try to modify a static variable using an object reference or self, Python doesn't directly modify the static variable. Instead, it creates a new instance variable with the same name in that particular object's namespace. This new variable only affects that specific object.

  • Deletion: Similarly, trying to delete a static variable using an object reference or self will lead to an AttributeError. Python restricts the deletion of static variables using these references.

Note: We can modify or delete static variables only by using the class name or cls variable.

Example:

# Define a class named Test
class Test:
    a = 10

# Create an instance t1 of the Test class
t1 = Test()

# Attempt to modify 'a' using object reference
t1.a = 70

# Explanation:
# Modifying 'a' using an object reference creates a new instance variable 'a' for 't1'.
# It doesn't modify the original static variable 'a'.

# Attempt to delete 'a' using object reference
del t1.a  # AttributeError: 'Test' object attribute 'a' is read-only

# Explanation:
# Deleting 'a' using an object reference results in an AttributeError.
# Python doesn't allow deleting static variables using object references.

This example showcases the behavior of modifying and deleting static variables using object references or self, and highlights the correct approach of using the class name or cls variable for such operations.