Question

Take the following code in C/C++, for example:

int foo[] = {0, 0, 0, 0};

No magic numbers, right?
Now, the Python "equivalent" of that would be:

foo = [0, 0, 0, 0]

Still no magic numbers.
However, in Python, that same thing can be written like this:

foo = [0] * 4

And now we DO have a magic number. Or do we?
I'm guessing this and other similar things are present on these and other languages.

Was it helpful?

Solution

Not every number is a magic constant. The reason 4 and the four 0 are magic numbers (in any language) is that it's entirely unclear why that number is 4 and not any other number.

For example in the context of a game that is played with the well known six-sided die

def roll_die():
    return random.randint(1,6)

this code has no magic numbers, because it's very easy to see where the numbers came from.

On the other hand it can be hard to guess which numbers other programmers know. For example, not everyone might know the number of cards in a deck, so it makes more sense to use a named constant there.

It entirely depends on the context if a number is "magic" or not, it has nothing to do with the language. When in doubt, name your constants just to be on the safe side.

OTHER TIPS

How's that different from (in C or C++):

int foo[4] = {0};

?

The size of the array is a magic number in all these cases.

Magic numbers, by the way I understand them, are domain values (used in calculation, indexes in mapping elements). The idea of them is consistent throughout any language. In your example, it depends on what these arrays are for.

See the below code. It is a c language feature.

  int arr[] = { [0 ... 4]=3,[7]=7,[8 ... 12]=12,[15]=0};

is same as

int arr[] = { 3, 3, 3, 3, 3, 0, 0, 7, 12, 12, 12, 12, 12, 0, 0, 0 };

All your question shows is that the concept of "magic numbers" and rules against using "magic numbers" in your program are completely and utterly idiotic. Rules against magic numbers are poor approximations, by people who don't understand what they're doing, of a much saner rule against hard-coding in multiple places values which must agree or which depend on one another. For instance, this code is perfectly reasonable, as long as the buffer length does not need to match anything else in the program or real world:

char buf[100];
snprintf(buf, sizeof buf, ...);

But this code is highly bad:

char buf[100];
snprintf(buf, 100, ...);

Of course in the real world there probably is something you want the buffer size to match, for instance the max number of digits needed to print an integer of some particular size. In this case, you might want something like:

char buf[3*sizeof(int)+3];
snprintf(buf, sizeof buf, ...);

And if you consider CHAR_BIT to be variable then you might want to replace 3 with a formula in terms of CHAR_BIT. In any case, the constants appearing in the expression are not "evil magic numbers".

In your example, if the dimension of the array is dependent upon some other variable, then all three of your array definitions are bad practice. But if the dimension 4 is fundamental to what you're doing, I don't see anything wrong with it.

Of course, what you're doing can sometimes change during the lifetime of code, but that's what documentation is for. Code cannot be expected to handle ever possible future change-of-purpose without some level of modification, and as long as you documented what its original purpose and contracts are, it should not be hard for someone changing those to find the parts of the code that need changing.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top