Why no 'const' in Python? [closed]
Asked Answered
P

2

50

I come from C background and am learning Python. The lack of explicit type-safety is disturbing, but I am getting used to it. The lack of built-in contract-based programming (pure abstract classes, interfaces) is something to get used to, in the face of all the advantages of a dynamic language.

However, the inability to request const-cortectness is driving me crazy! Why are there no constants in Python? Why are class-level constants discouraged?

Psittacosis answered 25/6, 2013 at 7:42 Comment(5)
"There's no equivalent for constants in Python, as the programmer is generally considered intelligent enough to leave a value he wants to stay constant alone".Larhondalari
Because python coders know what they are doing and are not naive enough to modify variables that should be constants(in the C context)Hoban
@Vorac, If continue your thought, then why there is no int, double and char types in Python?.. Because it is dynamic language. If you want "mix" of Python and C you can take a look at Cython or Go cython.org golang.orgLarhondalari
Short answer: This is a matter of point of view. In a different topic, LISP programmers used to say that "memory allocation is too important to be left to the programmer". And "C Programmers Think That Memory Allocation Is Too Important To Be Left To The Compute" (B. Stroustroup). You could say exactly the same for type/const correctness.Handout
@DenisNikanorov Where are these "intelligent" python developers hiding?Kestrel
H
29

C and Python belongs to two different classes of languages.

The former one is statically typed. The latter is dynamic.

In a statically typed language, the type checker is able to infer the type of each expression and check if this match the given declaration during the "compilation" phase.

In a dynamically typed language, the required type information is not available until run-time. And the type of an expression may vary from one run to an other. Of course, you could add type checking during program execution. This is not the choice made in Python. This has for advantage to allow "duck typing". The drawback is the interpreter is not able to check for type correctness.

Concerning the const keyword. This is a type modifier. Restricting the allowed use of a variable (and sometime modifying allowed compiler optimization). It seems quite inefficient to check that at run-time for a dynamic language. At first analysis, that would imply to check if a variable is const or not for each affectation. This could be optimized, but even so, does it worth the benefit?

Beyond technical aspects, don't forget that each language has its own philosophy. In Python the usual choice is to favor "convention" instead of "restriction". As an example, constant should be spelled in all caps. There is no technical enforcement of that. It is just a convention. If you follow it, your program will behave as expected by "other programmers". If you decide to modify a "constant", Python won't complain. But you should feel like your are doing "something wrong". You break a convention. Maybe you have your reasons for doing so. Maybe you shouldn't have. Your responsibility.

As a final note, in dynamic languages, the "correctness" of a program is much more of the responsibility of your unit testings, than in the hand of the compiler. If you really have difficulties to made the step, you will find around some "code checkers". Those are PyLint, PyChecker, PyFlakes...

Handout answered 25/6, 2013 at 8:6 Comment(12)
What about automatic exception throwing when a const object gets modified?Psittacosis
@Vorac, It is a convention to not modify variables which "defined on a module level and written in all capital letters with underscores separating words".Larhondalari
Dynamic programming is no restriction. I should be able to def y(const x): easily. It's basically "yet another issue in python:Gills
I agree with Erik Aronesty -- const compliance can be checked at "compilation" time in many situations. It should be possible to guarantee that a variable will not directly be modified within a certain context even if its type is only determined at run time.Forbore
@Forbore I would not argue as I'm not specialized in that area, but what you suggest strongly reminds me of tainted analysis to check and propagate possible modification of a variable. Using static analysis, this is proven to be undecidable. On the other hand, you could add some run-time check, but there is an obvious overhead for that. The third way, which is probably the one I would have favored, was to made each and every data immutable.Handout
@SylvainLeroux True, but a watertight taint analysis may be beyond what is suggested here. A modest alternative would be a check at compilation time that in a given scope where a variable is declared as constant no line of code modifies the variable or associates it with a non-constant variable (e.g., through a function call). Something similar to the level of security that C++ offers. No need to trace each variable through to every possible outcome.Forbore
@Forbore Correct. If you only consider that simple model, it could be implemented as you mentioned it. But that means you have to somehow store the const status of parameters in the compiled files to work properly with pre-compiled libraries (name mangling?). And even then, does it really ensure const-correctness ? what about *args and **kwargs, or dynamic invocation of a function by name of through function object stored in variables or collections ("function pointers") ? Maybe I'm wrong, but I think even with your simple model, you would still need runtime constness check.Handout
Even in JS (from EcmaScript 2016) we have constants. Hope python will also receive this feature. How can we be sure in variables if they are not constants :)Connolly
This answer doesn't make any sense. Defining a value as a variable or const is primarily for data safety (and avoiding errors), not for the compiler. No mental gymnastics excuses the lack of const in Python. It's just a downside of Python, period.Gambeson
@Robo Robok. I cannot agree more. Coming from a C++ background and getting involved in my first large python project, I was shocked that I had to analyze a call hierarchy of 20+ functions just to explorer whether my function input argument gets modified.Agriculturist
@Agriculturist be prepared for more shocks with Python. It's a decent language, but a little overrated. It doesn't even have real interfaces.Gambeson
This makes no sense: "it seems quite inefficient to check that at run-time for a dynamic language". Dynamic languages are inherently inefficient, and they do a lot of work at runtime. Adding a const check at runtime would be a negligible overhead.Masinissa
B
3

I don't know why this design decision was made but my personal guess is that there's no explicit const keyword because the key benefits of constants are already available:

  • Constants are good for documentation purposes. If you see a constant, you know that you can't change it. This is also possible by naming conventions.

  • Constants are useful for function calls. If you pass a constant as a parameter to a function, you can be sure that it isn't changed. In Python functions are "call-by-value" but since python variables are references you effectively pass a copy of a reference. Inside of the function you can mutate the reference but if you reassign it, the changes do not persist outside of the function scope. Therefore, if you pass a number as a variable, it is actually passed "like" a constant. You can assign a new value to the variable. But outside of the function, you still got the old number

Moreover if there was a const keyword, it would create an asymmetry: variables are declared without keyword but consts are declared with a keyword. The logical consequence would be to create a second keyword named var. This is probably a matter of taste. Personally I prefer the minimalistic approach to variable declarations.

You can probably achieve a little more type safety, if you work with immutable data structures like tuples. Be careful however, the tuple itself can not be modified. But if it contains references to mutable objects, these are still mutable even if they belong to a tuple.

Finally you might want to take a look at this snippet: http://code.activestate.com/recipes/65207-constants-in-python/?in=user-97991 I'm not sure if this is an implementation of "class-level constants". But I thought it might be useful.

Bouncer answered 25/6, 2013 at 8:12 Comment(5)
There is no asymmetry: def y(const x): variable still has no keyword. consts, which are not "variable" have keywordsGills
Be wary that only immutable objects passed to a function call are "passed "like" a constant". Mutable objects (lists, user defined classes) can be modified. This is where const would be useful, to only allow reassignment not mutation of function parameters.Ashwin
@Ashwin Pass an immutable object instead, if you don't trust the function enough to not mutate what you pass it. But keep in mind the Python mantra: "We're all consenting adults here". If a function mutates an object, it should be documented as such. If it doesn't, it should be documented as not.Purdah
@Purdah yeah I'm aware, I was just highlighting that the answer might be misread as suggesting that parameters are "passed "like" a constant", when that's only for certain types. It's a good point you make about documenting the behaviour of a function, and that's what I like about the const keyword in other languages - it documents the behaviour, but in an enforced way so that the documentation must be correct (if constness is stated).Ashwin
"Constants are good for documentation purposes": this is really not the point of constants... the point of a constant is to protect the programmer (and the program user) from accidentally changing something that is not supposed to be changed.Masinissa

© 2022 - 2024 — McMap. All rights reserved.