用单个下划线命名未使用的变量是不好的做法吗?


44

通常,当语言的语法要求我命名一个从未使用过的变量时,我将其命名为_

在我看来,这减少了混乱,让我专注于代码中有意义的变量。我发现它不引人注目,因此可以产生“视线之外,头脑混乱”的效果。

我执行此操作的一个常见示例是在SQL中命名子查询。

SELECT *
FROM
(
    SELECT *
    FROM TableA
    JOIN TableB
        ON TableA.ColumnB = TableB.ColumnB
    WHERE [ColumnA] > 10
) _ --This name is required, but never used here
ORDER BY ColumnC

另一个示例是未使用的循环变量。

array = [[] for _ in range(n)] # Defines a list of n empty lists in Python

仅当我觉得描述性名称未对代码添加任何内容,并且在某种意义上通过添加更多要记住的名称来消除它时,我才非常谨慎地使用该技术。在某些方面,我认为它类似于varC#中的关键字,我也很少使用它。

我的同事不同意。他们说,即使只有一个(字母)字符名称也比更好_

我错了吗?这样做是不好的做法吗?


4
我认为变量名应遵循信息论,即长度是使用它们的对数倒数概率(普通变量简称)。单个字母似乎是错误的处理方式。
dan_waterworth 2012年

2
@dan_waterworth在SQL脚本中,使用单字符或双字符作为表别名是一种很常见的做法。由于通常必须编写许多[table].[column]标识符,因此使用会大大提高可读性[T].[column]。这当然取决于脚本。这样的选择非常好,但是如果脚本很大,我可能会使用更具描述性的名称。
CodexArcanum'5

5
我希望您使用“虚拟”。这让我大叫,因为它们需要一种在这几行之外没有语义上下文的变量。_对一个人读不太好。(我讨厌PERL的原因之一-我无法输入或阅读它)
克里斯·库德莫

1
旁注:您要命名的是派生表,而不是子查询。
尼克·查马斯

2
c#中的var关键字没有这个含义,它只是一个推断类型的普通变量声明。
Francesco De Vittori'5

Answers:


60

所有名称都应有意义。如果这_是您的公司或整个社区中众所周知的标准,那么作为“无关紧要的名称”将是有意义的。如果不是这样,我会说这是不好的做法。请使用描述性名称作为您指的名称,尤其是因为该名称将来可能会很重要。


13
+1。 dummy会更好,joined_ab会更好。
Blrfl 2012年

5
+1,有一个约定,我要对未使用的变量使用'_'。我认为这是一个很好的约定,但是对于OP的情况,我同意这个答案。理想情况下,代码库应看起来像是由一个人编写的。
dan_waterworth 2012年

20
“ _”是Python的知名标准。
尼尔G

2
另一方面,如果您的公司使用任何Perl,则使用$ _有时可能会导致令人惊讶的行为。
Plutor

2
在序言中,下划线表示该变量将是匿名的,因此未使用。
伊万

44

我会说这是可以接受的做法。在极少数情况下,我会认为大多数人是错误的,需要更新他们对最新编程思想的了解。在许多语言中,尤其是像Haskell和OCaml这样的基于ML的功能语言中,_用作“未使用”变量非常普遍。甚至不提供明确语言支持的Lua都鼓励按照_惯例将其用作占位符。

几种语言(Haskell,Lua和DI都让我难以置信)也提供了一种约定,即以下划线开头的变量不会生成有关“未使用的局部变量”的编译器警告,这会使_未使用的变量名最短。您可以使用类似的方法,_unused但我同意您的观点,这只会使情况变得混乱。


对于SQL的特定情况,我已经考虑过了,同事在这里可能是正确的。对于表别名,我通常使用单个大写字母(对于子选择,通常使用R(结果))。我认为使用*in selects是一件非常糟糕的事情,因为如果表发生更改,结果集也会发生意外更改。因此,我通常需要单个字符别名来标识我选择的列。如果您停止使用*,则不再需要“未使用”的名称。
CodexArcanum'5

11
严格来讲,至少在Haskell中,_它是模式,而不是变量。这是一个细微的差异,但是这意味着您可以像一样多次使用它(x, _, _) = ...,而尝试多次绑定同一变量将是一个错误。
hammar

12

在Python _中绝对可以接受。但是,它可能与gettext别名 冲突_()

其他常见的惯例是dummyunused; 单独或作为前缀。

一些代码分析工具了解这些约定,并且不会发出未使用的变量警告:


2
另外,_在python中使用for伪变量会与_最后返回的值发生冲突。例如,在解释器中,如果您5*5在第1行上执行;然后在第2 _行将具有值25。但是,如果您随后进行设置x,_ = (3,'not used'),则会发现它_现在是not used而不是直到您返回的最后一个值del _。您可能不应该使用_真实代码中的最后一个返回值;但是在尝试新东西时,在解释器中通常很方便。
jimbob博士2012年

4
好吧,_因为最后返回的值在交互式外壳程序中有效。
vartec

Lua也是如此。标准做法是使用_
sylvanaar,2012年

11

这取决于此代码将要存在的生态系统。如果_是表示“虚拟变量” /“未使用的输出”的公认标准,那么一定要坚持下去。如果不是,请找出是什么并使用它。

某些编程语言(例如Haskell)甚至在您的语法中都内置了“特殊”标识符,以完全满足您提到的目的。


5

小心,_在某些语言中已经具有内在含义

在Python中:

9.6。私有变量和类本地引用

在此输入链接的描述不能从除对象内进行访问Python中不存在“私有”实例变量。但是,大多数Python代码遵循一个约定:以下划线开头的名称(例如_spam)应被视为API的非公开部分(无论是函数,方法还是数据成员) 。它应被视为实现细节,如有更改,恕不另行通知。

PEP 8(Python代码样式指南)中还提到了另一个:

描述性:命名样式

_single_leading_underscore:“内部使用”指标较弱。例如,从M import *不会导入名称以下划线开头的对象。

在C#中:

它通常用于标记具有公共/内部属性的私有变量。但是这些日子普遍被鄙视

在JavaScript中:

有一个名为underscore.js的库,该库使用下划线作为非标准原型扩展的前缀。

例:

var object = { some:'stuff' };
var newObject = _.clone(object);

这使我明白了这一点。经典的占位符变量约定有什么问题。

var i, j, k, l; // iterator placeholders
var x, y, z, xx, yy, zz // value placeholders
var foo, bar, bas, fixx, buzz, qux, etc... // demonstration placeholders

当已有许多通用约定可用时,为什么要使用某些人可能会误解的自定义约定?


在Scala中:它是通配符/占位符,但是作为占位符,您只能引用一次
雷克斯·克尔

@RexKerr有趣。如果需要,可以随意将其编辑为答案。我可以,但是我对scala不熟悉。
Evan Plaice 2012年

应该发表评论。任何使用Scala的人都会知道,而未使用Scala的任何人可能在做/不做某事的原因列表的顶部都没有Scala兼容性。
Rex Kerr

我认为对那些未使用的变量使用这些“约定”占位符中的一个是一种不好的做法,因为这会让我想到:“为什么这个家伙没有更好地命名这个东西?” 一段时间后,我发现这是因为未使用该变量。
igorsantos16 '04

@ igorsantos07我完全同意。我更愿意给出一个描述性的名称,即使是临时变量也是如此。这个答案的目的是说明为什么下划线不是命名约定的好选择;由于它在多种语言中都已存在。
Evan Plaice

2

我用“虚拟”来做这种事情。或“废话”,如果我只是测试一些东西:)命名您的变量以描述它们是什么。如果它们是虚拟的,未使用的变量,请这样命名。


0

我发现这是不好的做法,因为

  • 您的代码中不应包含不可见变量。如果您认为应该,可以讨论原因。

  • Go语言使用此关键字表示没有变量是函数的多个返回之一的目的地。如果您的语言没有多次返回,则不需要。当您使用以_作为标准语言符号的语言时,您的命名约定会伤害您。

(我不了解Python:是否真的需要此构造?)


2
如果您使用它来过滤多个返回值,那么也就将它用于伪函数参数。实际上,两者之间并没有太大区别:在模式匹配功能语言中,您可以编写let (a,b,_) = f(x,y,z)和一样好的let f(x,y,_) = (g(x),h(x),g(y))东西。—并且,是的,拥有伪参数通常很有用:不是作为函数的唯一定义,而是对于多态函数或具有替代模式匹配定义的函数,这通常是很自然的事情。
大约

1
您的第二点与您的要点相矛盾:在Go中,这实际上意味着与“我没有用这个值”相同。
Casey Kuball 2012年

0

它在语法上可能是有效的,并且作为标准的一部分可能还不错。

话虽如此,我要有人在代码审查中进行更改。我也永远不会将其放入编码标准中,并且会尝试将其从现有标准中删除。这只是更难阅读,而且没有超级意义。


0

我认为这是错误的,因为:

1)由于像素不多,很难看到。

2)如果不止一个_,您怎么知道哪一个?-还是新开发者已“遵循规则”,并在范围上将其使用限制在本地?

3)这是没有帮助的做法。使用单字母变量名称太老了(即我的原始教育!)。我将看到它们……然后看到添加注释以说明代码的功能,这在当今世界是一种不好的做法。我尽可能使用长变量名,这样每个人,无论编程水平或对代码的熟悉程度如何,都可以像英语一样“读”它。对于较旧的代码和较旧的程序员(再次包括我),使用1个字母名称是一种极为常见的做法,但这并不可行。


9
“你怎么知道哪一个” 你不知道:这也正是这一点,你使用变量。因此,是否_已经在外部范围中使用也无关紧要;这样一来,它就会被遮盖(或在这种情况下您的语言会执行任何操作),但是无论如何实际上都不会使用它们。
大约

0

为了避免名称空间冲突并允许进行调试,以防万一变量名是您的唯一线索,最好将其命名为“ joined_ab_unused”。

受到Birfl的启发。


0

是的,这是一个不好的做法,原因有两个:

  1. 用下划线给未使用的变量加上前缀不是公认的标准。很可能会忽略“未启动”。
  2. 我见过一些人前缀私有成员变量以下划线,你的标准会大大迷惑这样的人。

0

您要尝试的是在更好的SQL版本中进行编码,而不会出现强迫您为无用的东西命名的问题。

下划线几乎是看不见的,因此看起来您使用的是这种语言。如果只有空白可以用作标识符,那将是完美的,对吗?

但是您使用的语言并不相同,您所做的也不是进行语言扩展的干净方法。


0

这取决于语言。在java中,是的,这很不好,并且可能会成为添加到代码中的危险趋势,主要是因为使用反射的工具不能很好地处理下划线,因为它们不在Java变量命名约定之内。在python中,这也很糟糕,但还不错。在clojure中,它100%可以,实际上,在let语句中使用_作为占位符是惯用法。

请记住,每种语言都有其自己的完整语法和成语集合,因此您必须根据这些成语而不是绝对的词来评估好坏。


5
我不同意这是python中的不良做法。这是一个广为人知的惯例
丹妮丝

0

这在perl中是不好的,因为它使用$ _(有时是_)作为特殊变量。

通常,我会远离它,只是因为_似乎是一种可指定语言的语言。如果看到您的代码,我将在文档中查找_是什么,直到我意识到这只是一个虚拟对象。DUMMY,$ DUMMY没问题。


0

我会避免在vars开头使用下划线,除非您确定它们不会倾向于在给定的语言或框架中大量使用其他内容。例如,在Python中,双下划线往往表示魔术变量。在JQuery和其他JS库中,单个下划线往往表示名称空间覆盖的后备var。它也是包含文件的流行命名约定,而包含文件又倾向于继承到处理以var形式包含的代码。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.