This has been discussed before, and various problems have been raised, Iād suggest you search for previous threads in this forum to get an idea of what issues you need to address.
Beyond that, you havenāt provided enough of an actual proposal to really comment. Obviously, just making PI constant in the code you posted is not backward compatible, and so is a non-starter. If you werenāt aware of that, you should read up on Pythonās backward compatibility policies - this is a good place to start.
So how would a variable be marked as constant? What does āconstantā even mean - for example, can you have a constant list? If so how do you propose handling calls to mutating methods like append? And if you canāt have a constant list, what types are allowed to be used as constants? Can 3rd party types declare themselves as āpossible constantsā?
I suggest you do some background reading, and then flesh out your proposal if you think you still have something new to propose which hasnāt been discussed before.
Yeah, well, softwareās full of that sort of thing This is hardly the first time anyoneās used āconstant variableā for this sort of thing. āNamed constantsā might be better, but it might be easier to name the proposal by what it concretelty does, eg ācompile-time name resolutionā or similar.
But if you search the web for āconstant variableā, youāll find plenty of other places where the term is used.
The typical workaround is to make the named constants (which are really global variables) default values to non-public parameters so theyāre loaded as fast locals:
My main concern is whether, even after putting in all the effort this would entail, there would actually be a significant improvement.
But Iāll explain what Iāve been thinking:
My idea would be to add a new hint that is const (it would be clearer if it could be done like in other languages āāand use const variable_name = ..., but I donāt think thatās possible in Python).
Something like this:
from typing import Const
PI: Const[float] = 3.14159
def calculate(radius):
return 2 * PI * radius
In other words, declaring a variable as a constant should replace the places where it is used with the content of that variable.
This solution would save the interpreter from having to perform dictionary searches to check the value of the variable
The main doubts and problems I have encountered are the following:
What if a constant variable is inside a module that is imported at runtime?
It would become constant at the moment the value was assigned.
What happens if the constant variable is the result of a function that changes its result on each call?
It keeps the first value that has been assigned to it.
If a list is constant, are its elements constant?
You would need to define whether you want the list to be constant, whether the list contains constant elements, or whether the constant list contains constant elements; that is, it could be:
Const[list], list[Const], Const[list[Const]]
This proposal would simply mean that if a constant variable is being called anywhere, before execution, that variable would be replaced with its value.
Further research might explore optimizing the PyObjects of elements declared as const.
Perhaps adding a hint isnāt the best way to indicate a constant value; perhaps a constructor could be used, doing something like PI = Const(3.14).
You should not be using type hints, i.e. type annotations for something that actually affects the runtime as a core part of the language.
What happens if the constant variable is the result of a function that changes its result on each call?
It keeps the first value that has been assigned to it.
This is semantically confusing. If itās a constant in the way you are describing it doesnāt have a moment at runtime where the assignment is executed - this is what it means for it to be compile time expanded. Complex compile time evaluation is a whole new rabbit hole with weird implications.
Your mental model of how python currently works is incomplete to the point where part of your proposal is nonsensical. I would suggest doing more research, as well as reading up on previous discussions and e.g. PEP 795 which is related.
I think an actual named constant can be touted as one of the use cases of a syntactic macro (e.g. defining PI a macro of 3.14), which Mark Shannon wrote PEP 638 ā Syntactic Macros | peps.python.org for.
My own thoughts on the matter is there could be a way to mark the reference as fixed for as long as it is in scope, preferably with a Python-specific word because āconstā has too many definitions already.
A fixed reference to an immutable type (number, string or tuple) would be a constant in all but name.
Types that were mutable would remain mutable in place but with the guarantee that the reference couldnāt be reassigned while it remained in scope. Admittedly this would be of limited use, but the behaviour would be consistent.