在Python函数调用中用于未使用的返回参数的样式


30

是否有任何推荐的/普遍接受的编码样式用于处理以下情况:函数返回一个值的元组,但之后仅使用这些值中的一个(请注意,这主要是我无法更改的库函数的意思–编写包装器这个电话可能有点矫kill过正...)?而不是做

a, b, c = foo()

然后不使用band c,则应首选以下哪个变体(或还有另一个变体?):

变体1(下划线)

a, _, _ = foo()

(这非常简单明了,但可能会_ = gettext.gettext在许多使用翻译的应用程序中使用)

变式2(虚拟名称)

a, unused, unused = foo()

(我认为这不是很吸引人,其他名称也是如此dummy

变体3(索引)

a = foo()[0]

(对我来说,这些()[0]看起来很不可思议……)


与我以前的答案相反,当您现在要引用返回值的2/3时,变量3会发生什么?我删除了答案,因为我意识到我对Python的了解不足以证明其合理性。
Craige

@Craige:在删除答案之前,我没有看到您的答案...您是否正在询问是否a, b = foo()[0:2]可行?如果是:是,那么它是:)
user49643

那正是我要的。如果该方法有效(如您所说的那样),我将使用变体3。鉴于此信息,我将恢复我的回答。
Craige

3
顺便说一句,如今,您可以使用相当漂亮的语法来进行“扩展”解包a, *_ = foo()将丢弃除第一个值以外的所有值。
本杰明·霍奇森

Answers:


17

对未使用的变量使用下划线绝对可以接受。但是请注意,在某些代码库中,这不是一个选择,因为该标识符保留为的简写形式gettext。这是对这种风格的最常见的异议(尽管据我判断,这对于大多数人来说不是问题)。我仍然会推荐它,并且总是自己使用它。

名称喜欢dummyunused倾向于使我个人烦恼,而我却很少见到它们(在Python中,即-我知道一个Delphi代码库使用dummy得很广泛,并且也泄漏到了与该程序相关的脚本中)。我建议你反对。

从返回的元组中提取一项也是可以的。正确设置未使用值的数量还可以节省一些麻烦。请注意,尽管有两个潜在的缺点:

  • 如果值的数量与您期望的不同,它不会崩溃。这对于检测混淆和错别字可能很有用。
  • 它仅在返回值是序列时才有效(主要是元组和列表,但让我们保持常规)。另外,我知道我的代码中的一个类(2D向量)可迭代并产生恒定数量的值(因此可用于解压缩赋值),但不可索引。

确实在问题中提到了gettext :)无论如何,我接受了您的答案-似乎没有明确的单一接受样式,但是您的答案提出了一些有趣的观点。
user49643 2012年

为避免gettext出现问题(或避免在解释器中出现类似问题),可以使用双下划线(又名dunder)代替单下划线。
Zim

21

皮林特让我养成了这样的习惯:

widget, _parent, _children = f()

也就是说,未使用的结果具有以_开头的描述性名称。Pylint将前缀为_的局部变量视为未使用,并将前缀为_的全局变量或属性视为私有。


3

如果在您的整个项目中只执行一次此操作,或者很少使用特定功能,那么如果您知道gettext该模块中没有问题,则可以使用变体1 ,否则使用变体3。

另一方面,如果您经常这样做-特别是每次您想要不同的返回值子集(使包装器只返回您关心的不可行的返回值)时,编写包装器可能会有所帮助将结果放入一个命名的tuple或其他描述性类的实例,这将使您能够执行以下操作:

bar = foo()

然后一起工作bar.abar.bbar.c


2

正如其他人所说,下划线(_)是标准。但是,如果将下划线用于翻译,则我认为双下划线是最好的选择。

var, __, value = "VAR=value".partition('=')

比这些更好:

var, unused, value = "VAR=value".partition('=')

var, unused_del, value = "VAR=value".partition('=')

var, _del, value = "VAR=value".partition('=')


1

我不是Python程序员,但对我而言,第三个变体最有意义。

在变式3中,您绝对清楚要处理哪些值。在变体1和2中,您将这些值分配回变量,因此可以使用它们。您可能给它们起了个模糊的名字,但是不好的命名并不是解决任何问题的办法。

除了清楚之外,为什么还要将未使用的值分配给内存中的插槽(如变体1和2)?就内存管理而言,这将是一个糟糕的解决方案。


如果您始终将其放在同一个变量上,那么在任何给定时间,内存问题不是仅仅是单个变量的大小吗?我认为这不是问题。
Michael McQuade

-2

这是一条通用规则:如果仅使用返回值中的1个,为什么不简单地返回该1个值呢?如果从多个位置调用该标志,请保留相同的标志,并根据该标志返回值。

编辑:

如果我处于您的情况下,而我没有编写函数,则可能会选择Variant2。我会在其中保留虚拟名称,以便在需要时可以使用参数。切片列表将有一些开销。也许您可以保留几个字节来接收不需要的数据。


-1我猜他没有定义函数,因此无法更改它返回的内容。我认为他指的是该函数何时返回3个值,但是他在当前用例中只关心1个值。
Craige

@Craige:是的,我的意思是我无法更改的功能-我在问题中添加了一条便条以澄清这一点。
user49643 2012年

您确定开销吗?我尝试了一个非常简单的ipython测试:%timeit a, _, _ = foo()vs %timeit a = foo()[0].结果为123ns与109ns,即切片实际上比值拆包要快。还是您有任何特定的想法?
user49643 '13

2
另一个可行的情况是,某些呼叫不需要所有值。
基思·汤普森
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.