以 C/C++ 中的以下代码为例:
int foo[] = {0, 0, 0, 0};
没有神奇的数字,对吧?
现在,Python“等效”将是:
foo = [0, 0, 0, 0]
仍然没有神奇的数字。
然而,在 Python 中,同样的事情可以这样写:
foo = [0] * 4
现在我们确实有一个神奇的数字。还是我们?
我猜这和其他类似的东西出现在这些和其他语言上。
以 C/C++ 中的以下代码为例:
int foo[] = {0, 0, 0, 0};
没有神奇的数字,对吧?
现在,Python“等效”将是:
foo = [0, 0, 0, 0]
仍然没有神奇的数字。
然而,在 Python 中,同样的事情可以这样写:
foo = [0] * 4
现在我们确实有一个神奇的数字。还是我们?
我猜这和其他类似的东西出现在这些和其他语言上。
不是每个数字都是一个神奇的常数。原因4
和四个0
是神奇的数字(在任何语言中)是完全不清楚为什么这个数字是4
而不是任何其他数字。
例如,在使用众所周知的六面骰子进行的游戏中
def roll_die():
return random.randint(1,6)
这段代码没有神奇的数字,因为很容易看出数字的来源。
另一方面,很难猜测其他程序员知道哪些数字。例如,并不是每个人都知道一副牌中有多少张牌,所以在那里使用命名常量更有意义。
一个数字是否“神奇”完全取决于上下文,它与语言无关。如有疑问,为安全起见命名常量。
这与(在 C 或 C++ 中)有何不同:
int foo[4] = {0};
?
在所有这些情况下,数组的大小都是一个神奇的数字。
以我理解的方式,幻数是域值(用于计算,映射元素中的索引)。他们的想法在任何语言中都是一致的。在您的示例中,这取决于这些数组的用途。
请参阅下面的代码。它是交流语言功能。
int arr[] = { [0 ... 4]=3,[7]=7,[8 ... 12]=12,[15]=0};
和
int arr[] = { 3, 3, 3, 3, 3, 0, 0, 7, 12, 12, 12, 12, 12, 0, 0, 0 };
您的所有问题都表明,“幻数”的概念和禁止在程序中使用“幻数”的规则是完全愚蠢的。对于不了解自己在做什么的人来说,针对幻数的规则是很差的近似值,对于在多个地方硬编码必须一致或相互依赖的值的更明智的规则。例如,这段代码是完全合理的,只要缓冲区长度不需要匹配程序或现实世界中的任何其他内容:
char buf[100];
snprintf(buf, sizeof buf, ...);
但是这段代码非常糟糕:
char buf[100];
snprintf(buf, 100, ...);
当然,在现实世界中,您可能希望缓冲区大小匹配,例如打印某个特定大小的整数所需的最大位数。在这种情况下,您可能需要以下内容:
char buf[3*sizeof(int)+3];
snprintf(buf, sizeof buf, ...);
如果您认为CHAR_BIT
是可变的,那么您可能希望将 3 替换为CHAR_BIT
. 无论如何,表达式中出现的常量都不是“邪恶的幻数”。
在您的示例中,如果数组的维度取决于其他一些变量,那么您的所有三个数组定义都是不好的做法。但如果维度 4 是你所做工作的基础,我认为它没有任何问题。
当然,您所做的事情有时会在代码的生命周期内发生变化,但这就是文档的用途。如果不进行某种程度的修改,就不能期望代码能够处理将来可能发生的目的变更,并且只要您记录了其原始目的和合同是什么,那么更改这些内容的人应该不难找到代码的部分那需要改变。