`final` keyword equivalent for variables in Python?

Python 3.8 (via PEP 591) adds Final variables, functions, methods and classes. Here are some ways to use it:

@final Decorator (classes, methods)

from typing import final

@final
class Base:
    # Cannot inherit from Base

class Base:
    @final
    def foo(self):
        # Cannot override foo in subclass

Final annotation

from typing import Final

PI: Final[float] = 3.14159     # Cannot set PI to another value
KM_IN_MILES: Final = 0.621371  # Type annotation is optional

class Foo:
    def __init__(self):
        self.bar: Final = "baz"   # Final instance attributes only allowed in __init__

Please note that like other typing hints, these do not prevent you from overriding the types, but they do help linters or IDEs warn you about incorrect type usage.


Having a variable in Java be final basically means that once you assign to a variable, you may not reassign that variable to point to another object. It actually doesn't mean that the object can't be modified. For example, the following Java code works perfectly well:

public final List<String> messages = new LinkedList<String>();

public void addMessage()
{
    messages.add("Hello World!");  // this mutates the messages list
}

but the following wouldn't even compile:

public final List<String> messages = new LinkedList<String>();

public void changeMessages()
{
    messages = new ArrayList<String>();  // can't change a final variable
}

So your question is about whether final exists in Python. It does not.

However, Python does have immutable data structures. For example, while you can mutate a list, you can't mutate a tuple. You can mutate a set but not a frozenset, etc.

My advice would be to just not worry about enforcing non-mutation at the language level and simply concentrate on making sure that you don't write any code which mutates these objects after they're assigned.


There is no final equivalent in Python.

But, to create read-only fields of class instances, you can use the property function.

Edit: perhaps you want something like this:

class WriteOnceReadWhenever:
    def __setattr__(self, attr, value):
        if hasattr(self, attr):
            raise Exception("Attempting to alter read-only value")

        self.__dict__[attr] = value

Edit many years later: as Cerno mentions, as of Python 3.8 there's @typing.final. Do note that there's no runtime checking for this property.