[Python-ideas] Change magic strings to enums

Chris Angelico rosuav at gmail.com
Tue Apr 24 13:42:27 EDT 2018


On Wed, Apr 25, 2018 at 3:19 AM, Steven D'Aprano <steve at pearwood.info> wrote:
> On Wed, Apr 25, 2018 at 01:18:10AM +1000, Chris Angelico wrote:
>
>> First, though, can you enumerate (pun intended) the problems with
>> magic strings? You list "no magic strings" as a benefit, as if it's
>> self-evident; I'm not sure that it is.
>
> It shouldn't be self-evident, because the use of strings in the warnings
> module doesn't match the most common accepted meaning of magic strings.
>
> https://en.wikipedia.org/wiki/Magic_string
>
> Possibly Jacco was thinking of "magic constants":
>
> https://en.wikipedia.org/wiki/Magic_number_%28programming%29#Unnamed_numerical_constants
>
> (although in this case, they're text constants, not numerical).

I assumed this to be the case, yes. Many people decry "magic numbers"
where the number 7 means one thing, and the number 83 means something
else; but I'm less convinced that the textual equivalent is as
problematic.

(If not "magic strings", what would you call them?)

> A fairly lightweight change would be to add named constants to the
> warning module:
>
> ERROR = 'error'
>
> etc, and refactor the module to use the named constants instead of
> hard-coded strings. I'm surprised that it doesn't already do that.
>
> That would be 100% backwards compatible, without the cost of importing
> and creating enums, but allow consumers of the warnings module to
> inspect it and import symbolic names if they so choose:
>
> from warnings import ERROR

Yeah, that would be one way to do it. But I'd still like to know what
problems are being solved by this, as a means of determining whether
they're being solved adequately. Is it the risk of misspellings?
Because that can happen just as easily with the imported name as with
a string literal. (The from-import pollutes your namespace, and
"warnings.EROR" is a run-time failure just as much as a misspelled
string literal would be.) Is it the need to list all the possible
strings? That could be done with something like
__future__.all_feature_names or the way the logging module translates
level names into numbers. Something else?

ChrisA


More information about the Python-ideas mailing list