【问题标题】:Unneeded parts when unwrapping tuple/list展开元组/列表时不需要的部分
【发布时间】:2011-12-02 19:58:27
【问题描述】:

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]

但这远不那么可读。

【问题讨论】:

    标签: python variable-assignment pylint


    【解决方案1】:

    除了@RaymondHettinger 的回答:如果它们的名称以单个下划线开头,Pylint 也不会抱怨未使用的变量。这意味着您可以使用:

    for _myvar1, myvar2 in mylist:
    

    两全其美:

    • 没有 Pylint 警告,
    • 以及有关记录结构的信息

    这也适用于函数/方法原型,并避免有关未使用参数的警告,当您从 OO 框架中的基类派生时经常会得到这些警告。

    【讨论】:

    • 所以这意味着_也没有Pylint警告?
    • 如果 Pylint 的名称以unused_(字面意思)开头,似乎 Pylint 不会抱怨未使用的变量。例如。 for unused_myvar1, myvar2 in mylist:。前缀unused_that answer 中描述了相关问题。
    【解决方案2】:

    你尝试过其中任何一个吗?

    for _, myvar in mylist:
        #Do stuff
    

    在 Python 中运行良好,并且相对地道。

    【讨论】:

    • 是的,它确实有效。但它确实将元组的第一个值分配给变量_,这不是我的问题的想法
    • 好吧,你已经列出了你的选择,我会说这是最“漂亮”的。正如您所说,其他选项更冗长且不易理解。 Pylint 是一个很好的工具,但它并不是代码美的全部(无论这意味着什么)。
    • 对我来说这是非常地道的。
    【解决方案3】:

    当我想强调只使用 myvar2 时,我写了for _, myvar2 in mylist

    当我想提醒读者(通常是我)记录结构是什么时,我会写for myvar1, myvar2 in mylist

    _ 名称只是一次性值的命名约定。 CPython 解释器为它分配变量,就像它对任何其他变量名一样(幸运的是,*STORE_FAST* 是一个非常便宜的操作)。相比之下,PyPy interpreter 会将未使用的变量赋值识别为死代码,因此无论您如何编写它,您都可以免费获得优化。

    如果您对 CPython 如何解释您的代码感到好奇,dis module 可以提供有用的见解:

    >>> 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 不应该在这种情况下抱怨 _

    【讨论】:

    • pylint 也不会抱怨名称以单个下划线开头的未使用参数。这意味着您可以使用“for _myvar1, myvar2 in mylist”,获得两全其美:没有 pylint 警告和有关记录结构的信息。
    • 我会将此评论添加为@gurney-alex 的答案,因为我认为这是最好的。
    • @gurneyalex 这是一个很好的观察,我会调查一下。
    • @FrancisAvila,我就是这么做的。
    【解决方案4】:

    我想你可以这样做:

    for myvar in (t[1] for t in mylist):
        pass
    

    但坦率地说,我认为在这种情况下你应该忽略 pylint 警告——它足够漂亮,不会引起任何混乱(这就是你首先想要美丽的原因)。

    【讨论】:

    • 我猜你是对的。我问这个不是因为我想避免pylint 警告,而是出于好奇
    【解决方案5】:

    我会说 Python 就是为了编写可读代码 - 任何“美”都只是副作用。

    元组的第一项可以这样删除:

    for myvar2 in zip(*mylist)[1]:
        # Do stuff with myvar2
    

    但我不确定我是否真的会推荐它。我个人只会使用:

    for myvar1, myvar2 in mylist:
        # Do stuff with myvar2
    

    ...并忽略 pylint。

    【讨论】:

      【解决方案6】:
      tu = [(12,'sea'),(478,'badada'),(789,'zut')]
      
      for x,x in tu:
          print x
      

      结果

      sea
      badada
      zut
      

      !

      【讨论】:

      • 终于有一个合理的答案了,不是最好的办法,但至少回答了我的问题。
      • 这似乎不如使用不同的变量名漂亮和清晰,并且仅在您想忽略左侧的项目时才有效。你会自动知道哪个项目绑定到x 而不测试代码吗?实际上,这是 pylint 应该抓住的。
      • @Francis Avila 我并不难过,我只是很惊讶。关于您的观点,请参阅 (docs.python.org/reference/expressions.html#evaluation-order) 顺便说一下,您如何称呼 “指定行为” 以及它与 “实现” 的区别?
      • 这个答案不是一个很好的模型。许多读者会感到困惑。它不会通过大多数代码审查。
      • 否决这个答案。这是丑陋和邪恶的,并且不会通过我工作的代码审查,因为它会带来可维护性问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-05-26
      • 1970-01-01
      • 1970-01-01
      • 2016-06-18
      • 1970-01-01
      • 2015-03-23
      • 1970-01-01
      相关资源
      最近更新 更多