解包元组/列表时的多余部分

6 投票
6 回答
2809 浏览
提问于 2025-04-17 07:34

Python的核心就是写出优美的代码。所以,我在用pylint来检查我的代码是否优美时,遇到了一些问题:

未使用的变量 'myvar1'

这是我代码中的一部分:

for myvar1, myvar2 in mylist:
    # Do stuff just using myvar2

mylist是一个包含元组的列表,所以我把元组拆解成两个变量(myvar1myvar2)。我定义这两个变量只是为了提取第二个,因为我并不需要第一个。

所以,我的问题是:有没有办法告诉解释器只拆解元组,但不赋值给第一个部分(例如)。在其他一些语言中,你可以这样做:

for _, myvar in mylist:
    # Do stuff with myvar

或者

for *, myvar in mylist:
    # Do stuff with myvar

这意味着:我不关心元组的第一部分,我只需要第二部分。

注意:我知道这可能是我所问的一个选项:

for mytuple in mylist:
    # Do stuff with mytuple[1]

但这样写可读性差得多。

6 个回答

3

你试过这两个方法吗?

for _, myvar in mylist:
    #Do stuff

在Python中运行得很好,而且用法也比较符合常规。

3

我在写 for _, myvar2 in mylist 时,是想强调只有 myvar2 这个变量会被用到。

而我写 for myvar1, myvar2 in mylist 时,是想提醒读者(通常是我自己)这个记录的结构是什么样的。

这里的 _ 只是一个命名习惯,用来表示一个不需要的值。CPython 解释器会像处理其他变量名一样处理这个变量的赋值(幸运的是,*STORE_FAST* 这个操作是非常便宜的)。相比之下,PyPy 解释器 会把这个未使用的变量赋值识别为无效代码,因此无论你怎么写,它都会自动优化。

如果你对 CPython 如何解释你的代码感兴趣,可以使用 dis 模块 来获取一些有用的信息:

>>> from dis import dis
>>> def f(lot):
        for _, var2 in lot:
            print var2


>>> dis(f)
  2           0 SETUP_LOOP              25 (to 28)
              3 LOAD_FAST                0 (lot)
              6 GET_ITER            
        >>    7 FOR_ITER                17 (to 27)
             10 UNPACK_SEQUENCE          2
             13 STORE_FAST               1 (_)
             16 STORE_FAST               2 (var2)

  3          19 LOAD_FAST                2 (var2)
             22 PRINT_ITEM          
             23 PRINT_NEWLINE       
             24 JUMP_ABSOLUTE            7
        >>   27 POP_BLOCK           
        >>   28 LOAD_CONST               0 (None)
             31 RETURN_VALUE 

正如其他人提到的,pylint 的警告有时候可能很无聊。如果你喜欢在代码中使用短的变量名,那就忽略 pylint 的抱怨吧。正如 Francis Avila 指出的那样,在这种情况下,pylint 不应该对 _ 提出警告。

11

除了@RaymondHettinger的回答之外:Pylint不会对以单个下划线开头的未使用变量发出警告。这意味着你可以使用:

for _myvar1, myvar2 in mylist:

这样你就能得到两全其美的效果:

  • 没有Pylint的警告,
  • 同时还能获取记录结构的信息

这个方法同样适用于函数或方法的原型,能够避免关于未使用参数的警告,这种警告在面向对象的框架中从基类派生时经常会出现。

撰写回答