`final` keyword equivalent for variables in Python?
Solution 1
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.
Solution 2
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
Solution 3
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.
Solution 4
An assign-once variable is a design issue. You design your application in a way that the variable is set once and once only.
However, if you want run-time checking of your design, you can do it with a wrapper around the object.
class OnePingOnlyPleaseVassily(object):
def __init__(self):
self.value = None
def set(self, value):
if self.value is not None:
raise Exception("Already set.")
self.value = value
someStateMemo = OnePingOnlyPleaseVassily()
someStateMemo.set(aValue) # works
someStateMemo.set(aValue) # fails
That's clunky, but it will detect design problems at run time.
Solution 5
There is no such thing. In general, the Python attitude is "if you don't want this modified, just don't modify it". Clients of an API are unlikely to just poke around your undocumented internals anyway.
You could, I suppose, work around this by using tuples or namedtuples for the relevant bits of your model, which are inherently immutable. That still doesn't help with any part of your model that has to be mutable of course.
Related videos on Youtube
![Jason Coon](https://i.stack.imgur.com/VOqvL.jpg?s=256&g=1)
Comments
-
Jason Coon almost 2 years
I couldn't find documentation on an equivalent of Java's
final
in Python, is there such a thing?I'm creating a snapshot of an object (used for restoration if anything fails); once this backup variable is assigned, it should not be modified -- a final-like feature in Python would be nice for this.
-
Anderson Green over 10 yearspossible duplicate of Creating constant in Python
-
Apurva Singh over 6 yearsOverall.. lack of immutability is disastrous.. proves that Python is not suitable for large scale multi threaded apps.
-
antonagestam almost 5 years@ApurvaSingh While I agree that Python is not suitable for that, there are tuples and frozenset in the standard library and MagicStack/immutables is an implentation of a mutable mapping that will be proposed to be added to the standard library as well.
-
-
user1066101 about 15 yearsMany other classes are immutable, too: strings, ints, longs, floats.
-
IceArdor over 9 yearsIn Java, a non-primitive variable points to an object. Designating a variable as final means you cannot make the variable point to a different object, however the object that is being pointed to can be mutated.
-
Hatoru Hansou over 8 yearsThere is another use for final in Java, I think that it is the same as static in C++, and that is that the line of code assigning to a final variable is not executed more than once, even if declared inside a function. It allows you to hide the variable from the rest of the code without constantly construct new instances every time the functions is called. In Python you have to use a variable in the global scope or accept the cost of constantly construct new instances. cpp.sh/24gj
-
delucasvb over 5 yearsI find it an awful suggestion to
simply concentrate on making sure that you don't write any code which mutates these objects after they're assigned
. How will you communicate this to other people? Or to your future self? With a comment or docstring? A formal language construct is much less volatile than a comment. Python lacking this is, indeed, worrisome. -
John Strood over 5 yearsI always replace
self.__dict__[attr] = value
withreturn super(WriteORW, self).__setattr__(attr, value)
-
Charles Merriam over 4 yearsNo longer accurate for versions >= 3.8. See the @congusbongus answer below.
-
antonagestam over 4 yearsI think this answer is misleading as it's easy to get the impression that the final qualifiers will prevent one from reassigning or overriding at runtime, which isn't the case.
-
momo over 4 years@antonagestam it's a language feature. IDE's like Visual Studio Code and PyCharm will probably adapt and automatically show a warning if you try to reassign a final instance. This is already the case when you try to use an instance variable with an underscore prefix outside of the class.
-
antonagestam over 4 years@momo Just like a question about private properties should have an answer that explains that nothing is truly private in Python, I think an answer to this question suggesting using the
final
/Final
qualifiers should explain that they do nothing at runtime. Note that I answered this question too. -
Conchylicultor over 4 yearsI agree with @antonagestam comment.
@typing.final
is only used by static type checker. The answer should made it clearer that this decorator is entirely ignored when executing the script. Dynamically created classes will silently ignore this decorator. -
Denis Barmenkov over 2 yearsNB:
assert
statements are disabled by optimization with-O
CLI option, soif + raise
.