Python Equivalent to Java Final Keyword

Featured_image

In Java, the ‘final’ keyword is used for variables that cannot be reassigned to an object. Python being a dynamically typed language, earlier was short of this feature. But from the 3.8 version of Python, we do have a feature named “Final” from the typing module. However, we will also look into other tools present in Python, that will help us achieve a complete concept of immutability.

The ‘Final’ keyword, introduced in version 3.8, serves as an equivalent to Java’s final keyword, offering a way to declare variables and methods immutable. While it does not enforce immutability at runtime, it signals to type checkers like Mypy that certain elements should not be modified. This article explores Python’s approach to immutability, including alternatives like tuples and frozen sets, offering insights into achieving data constancy similar to Java’s final keyword.

Also Read: What is The Python Equivalent of ~/.bashrc?

Understanding the ‘final’ Keyword in Java

In Java, the ‘final’ keyword serves the following purposes:

Final Keyword in Java: Variables and Constants

Java allows users to declare variables and attributes as final. Once declared and assigned, they cannot be modified ahead in the program.

Java’s Final Keyword: Methods and Attributes in Sub-Classes

Java allows us to declare methods and attributes of classes as Final. When classes are inherited, Java doesn’t allow subclasses to override existing final methods of the parent class. Thus it is one of the properties of the final keyword to stop users from redefining methods declared as final.

Final Classes Cannot be Inherited

Similarly, final classes cannot be inherited by other classes in Java. The functions and attributes inside final classes are also final. Java also prevents extending such classes via interfaces.

Python’s Final Keyword Equivalent

From Python 3.8, the Final keyword was introduced in the ‘typing’ module of Mypy. Mypy is an optional type checker that is used to type-check the Python program.

Mypy and the ‘Final’ Typing in Python: To run the typing module, one should install Mypy using pip in their systems. Head over to references for more details.

Now, we look at some of the properties exhibited by the Final keyword.

Demonstrating Final Constants and Variables in Python

Likewise, Java, and Python allow users to declare variables and constants as Final. Once declared, they cannot be redefined, reassigned or overridden. This prevents modification at modular and class levels.

For example:

from typing import Final
# Variable declared as Final
MAX: Final = 9000
MAX = 1

class A:
# Attribute declared as Final
    TIMEOUT: Final[int] = 10

class B(A):
    TIMEOUT = 1  
Compilation_Error
Compilation_Error

Here we have two cases:

  • Variable declared as Final: The variable MAX is declared Final, which prevents us from assigning a new value in the third line.
  • Attribute defined as Final: Inside class A, an attribute “TIMEOUT” is defined as Final. After the class B inherits class A, the attribute “TIMEOUT” is also inherited as a property. But as it was declared Final, Python doesn’t allow us to assign a new value to the attribute.

    Illustrating Final Methods in Python

    Similarly, Mypy allows users to declare class functions, static functions, and instance functions as Final.

    from typing import final
    
    class Parent:
        @final
        def method(self) -> None:
            
    
    class Chlid(Base):
        def method(self) -> None:  # Error: cannot override a final method
    
    Compilation_Error
    Compilation_Error

    In this example, the child class tries to override the Final method in the parent class. Thus Python states a compilation error because the final methods cannot be redefined.

    Understanding Final Classes in Python

    Mypy allows one to make classes as final. It simply reflects that the classes cannot be subclassed.

    from typing import final
    
    @final
    class Leaf:
        
    class MyLeaf(Leaf):  # Error: Leaf can't be subclassed
        
    
    Compilation_Error
    Compilation_Error

    Here the catch is that decorator @final is used to inform Mypy about a class that should not be inherited. But it cannot prevent subclassing during runtime.

    Exploring Alternatives to Mypy for Immutability

    Rather than fussing over libraries, one can use immutable data structures to obtain a similar behavior.

    Immutability with Tuples in Python

    In Python, tuples are immutable sequences. By using tuples, we can create variables that cannot be modified once defined.

    For Example:

    # Creating an Immutable Tuple
    my_tuple = (1, 2, 3, "immutable", 5.5)
    my_tuple[0] = 10
    
    Tuple_error
    Tuple_error

    The example shows that once a tuple is created, its elements cannot be altered, making it an immutable data structure in Python. Hence operations like item assignment, remove, update and add are not present in Tuples because they cannot be modified, once declared.

    Named Tuples: A Pythonic Way to Immutable Objects

    NamedTuples provide a readable and convenient way to define immutable classes.

    For Example:

    from collections import namedtuple
    
    # Creating an Immutable Namedtuple
    Person = namedtuple("Person", ["name", "age", "city"])
    
    # Creating an instance of the named tuple
    person_info = Person(name="Alice", age=30, city="Wonderland")
    
    person_info.name = "Bob"
    
    NamedTuples_error
    NamedTuples_error

    Thus here we create a NamedTuple named as Person. During declaration of Person, we name the properties (name, age and city). Secondly we create an instance of the class, by providing the values to the attributes. Lastly, Python prevents us from modifying the instance’s attributes.

      Frozen Sets for Python Immutability

      Frozen Sets are immutable Set Objects that cannot have duplicate values.

      For Example:

      # Creating an Immutable Frozenset
      original_set = {1, 2, 3, 4, 5}
      
      # Creating a frozenset from the original set
      immutable_set = frozenset(original_set)
      
      immutable_set.add(6)
      
      Frozen_Set_Error
      Frozen_Set_Error

      Here the Attribute Error states that frozenset object do not have attribute like add because they are immutable. Hence operations like remove, update and add are not present in Frozen Set because they cannot be modified, once declared.

      Custom Classes for Immutability in Python

      Creating custom classes with read-only properties can also achieve immutability.

      For Example:

      class ImmutablePerson:
          def __init__(self, name):
              self._name = name
      
          @property
          def name(self):
              return self._name
      
      # Creating an instance of Immutable Person
      person = ImmutablePerson(name="Alice")
      
      # Attempting to modify the attributes directly would result in an error
      person.name = "Bob"
      
      Custom_Classes_Error
      Custom_Classes_Error

      In this example, when the attribute “name” of an instance person is changed, Python shows an Attribute Error. This is because “@property” is used to mark function “name” as read-only, which makes it immutable.

      Also Read: Oop – Python Equivalent of Java’s Compareto()

      Rules to Remember When Using Python’s Final

      1. When using Final from Mypy, keep the following things in mind:
      • Do not forget to install Mypy before starting your code.
      • At most one final declaration can be made at modular or class level for an attribute. There can not be a class level as well as instance level final declarations together.
      • When declaring an attribute as final, do assign a value to it. There can be one assignment to a particular final attribute.
      • Do not use final with arguments of a function.
      • Declaring a name as final guarantees that a particular value cannot be modified. But it doesn’t state that it is immutable. Therefore it is similar to the concept of immutability , but not same!

      Example: If we define an array as final , we can still append values to it. But cannot modify the existing values at initialized indices.

      1. In order to achieve complete immutability , use data-structures like Tuples, NamedTuples, Frozen Sets and Custom Classes.

      Is there an exact equivalent to Java’s ‘final’ keyword in Python?

      In Python, the closest equivalent to Java’s ‘final’ keyword is the typing.Final annotation introduced in Python 3.8 with the Mypy library. While typing.Final mirrors aspects of Java’s ‘final’, like restricting reassignment, it falls short of complete immutability. Therefore, Python developers often use other constructs like tuples, named tuples, frozen sets, and custom classes to achieve true immutability in their code.

      How does typing.Final in Python differ from true immutability?

      While typing.Final in Python prevents the reassignment of a variable, it doesn’t make the variable’s value truly immutable. A typing.Final variable guarantees that its reference won’t change, but the underlying data can still be mutable. For instance, a list declared as Final can’t be reassigned, but items within the list can still be modified, added, or removed. This characteristic differentiates it from complete immutability seen in languages like Java.

      What’s the best way to achieve immutability in Python?

      The optimal approach to achieve immutability in Python varies based on the specific requirements of your application. If type-checking and preventing reassignment are your primary concerns, use typing.Final from Mypy is a good choice. However, for complete immutability—where data structures cannot be altered after creation—relying on Python’s built-in immutable data types like tuples and frozen sets, or designing custom classes with read-only properties, is more effective.

      Conclusion

      As we’ve seen, Python’s approach to immutability, although different from Java’s final keyword, offers powerful alternatives. From the ‘Final’ keyword in Mypy to immutable data structures like tuples and frozen sets, Python provides a range of options to prevent data modification. Which approach will you choose for your next Python project?

      References