在解释性语言中使用匈牙利命名法前缀是否有意义?
首先,我查看了以下帖子,以避免重复提问。
https://stackoverflow.com/questions/1184717/hungarian-notation
为什么我不应该使用“匈牙利命名法”?
变量前缀(“匈牙利命名法”)真的还必要吗?
在现实中,人们真的使用匈牙利命名法吗?
现在,这些帖子都与C#、C++、Java等强类型语言有关。
我明白在编译之前,类型已知时,前缀是没有必要的。
不过,我的问题是:
在基于解释器的语言中,考虑到在运行时之前你看不到对象的类型,使用前缀是否值得?
编辑:如果有人可以把这个帖子变成社区维基,请这样做。我对这个帖子的声望(或负面声望)并不太感兴趣。
5 个回答
在我看来,使用系统匈牙利命名法(在变量名前加上数据类型)其实没什么意义。你要么使用静态语言,要么使用动态语言,但无论哪种,编译器或解释器都会处理类型系统。通过变量名来标注变量的类型只会造成混淆(比如想象一下有一个叫 intSomething
的浮点数)。
而应用匈牙利命名法就完全不同了,也就是在变量名前加上一些使用模式。我认为使用这种命名方式是个好习惯,比如用 'usValue' 来表示一个不安全(即未经验证)的值。这可以给你一个视觉提示,帮助你区分不同用途的变量,虽然它们的类型相同,但并不是要一起使用(或者当它们确实要一起使用时,至少你知道它们的用途,这样在检查代码时也能引起你的注意)。
我在 MATLAB 中经常使用这样的命名方式,比如用 idxInterest
来表示这个双精度数组不是原始数据值,而只是某种情况下感兴趣的索引(指向另一个数组)。我还经常用 selInterest
(sel
是 select 的缩写)来表示逻辑索引(我同意这可能看起来有点像系统匈牙利命名法),但在很多情况下,这两者可以在同一上下文中使用。
对于迭代器也是一样:我经常使用多维数组(比如 4D),在偶尔需要对某个维度运行 (par)for
循环时,迭代器的命名为 iFoo
、jBar
、kBaz
等等,而它们的上限通常是 nFoo
、nBar
、nBaz
等等(或者 numFoo
等等)。在进行更复杂的索引操作时,你可以很容易地看出哪个索引属于哪个维度(通过前缀你就知道使用了哪个数值维度,通过完整的名称你知道这个维度代表什么)。这样代码就更容易阅读了。
此外,我还经常使用 dFoo=1;
、dBar=2;
等来表示某组变量的维度编号。这样,你可以很清楚地看到像 meanIncome = mean(income, dBar)
这样的代码是对 Bar
维度的 income
取平均,而 meanIncome = mean(income, 2)
则没有传达同样的信息。因为你还需要设置 d
变量,这也算是对变量的一种文档说明。
虽然像 iFoo + jBar
或 kBaz + dBar
这样的写法在技术上并没有错,但当这些出现在你的代码中时,确实会引发一些疑问,这也让你能更仔细地检查那部分代码。这就是应用匈牙利命名法的真正意义所在。
(*) 唯一可能有意义的时刻是当你的整个框架或语言要求你使用它时。例如,win32 API 就使用这种命名法,所以当你直接与它接口时,应该遵循这些标准,以减少混淆。不过,我认为寻找另一个框架或语言可能更有意义。
请注意,这与 Perl、某些 BASIC 方言等语言中使用的 符号 是不同的。这些符号也传达类型,但在许多实现中,这就是类型定义,因此几乎没有或很少有混淆。至于使用这种类型声明是否是个好习惯,这又是另一个问题(我自己对此也不太确定)。
这要看你指的是哪种匈牙利命名法:
如果你想使用“真正的”原始匈牙利命名法,也就是应用匈牙利命名法,它是用来表示变量的逻辑类型或其用途的,那你可以随意使用。
另一方面,被“误解”的版本,也就是系统匈牙利命名法,仅仅表示变量的物理类型,这种用法是不被推荐的,不应该使用。
在Python中,使用匈牙利命名法来表示变量类型(也叫“系统匈牙利”)是不受欢迎的,原因很简单:它容易让人误解。比如,你可能会把一个变量命名为 iPhones
(表示手机的数量,可能是个整数 :-)),但因为Python的特性,你完全可以把其他类型的东西放进去!而且你可能真的会因为某些原因需要这么做。这样一来,所有使用这个变量的代码就会对想要理解它的人造成很大的困惑,除非你把这个变量的名字改成别的。
这种命名法最初是为了帮助你在静态类型语言中跟踪变量类型,曾经确实有用过一段时间。但现在已经过时了,即使在静态类型语言中也是如此,因为现在有很多更好的开发工具(IDE)可以完成这个工作。