【问题标题】:Is it possible to use 'else' in a list comprehension? [duplicate]是否可以在列表理解中使用“else”? [复制]
【发布时间】:2011-02-26 11:01:23
【问题描述】:

这是我试图转换为列表理解的代码:

table = ''
for index in xrange(256):
    if index in ords_to_keep:
        table += chr(index)
    else:
        table += replace_with

有没有办法将 else 语句添加到这个理解中?

table = ''.join(chr(index) for index in xrange(15) if index in ords_to_keep)

【问题讨论】:

    标签: python list-comprehension


    【解决方案1】:

    是的else 可以在 Python 中使用 list comprehension Conditional Expression(“三元运算符”):

    >>> [("A" if b=="e" else "c") for b in "comprehension"]
    ['c', 'c', 'c', 'c', 'c', 'A', 'c', 'A', 'c', 'c', 'c', 'c', 'c']
    

    这里的括号“()”只是为了强调条件表达式,不一定是必须的(Operator precedence)。

    另外,多个表达式可以嵌套,导致更多elses和更难阅读代码:

    >>> ["A" if b=="e" else "d" if True else "x" for b in "comprehension"]
    ['d', 'd', 'd', 'd', 'd', 'A', 'd', 'A', 'd', 'd', 'd', 'd', 'd']
    >>>
    

    在相关说明中,推导式还可以在末尾包含自己的 if 条件:

    >>> ["A" if b=="e" else "c" for b in "comprehension" if False]
    []
    >>> ["A" if b=="e" else "c" for b in "comprehension" if "comprehension".index(b)%2]
    ['c', 'c', 'A', 'A', 'c', 'c']
    

    条件s?是的,多个ifs 是可能的,实际上也是多个fors:

    >>> [i for i in range(3) for _ in range(3)]
    [0, 0, 0, 1, 1, 1, 2, 2, 2]
    >>> [i for i in range(3) if i for _ in range(3) if _ if True if True]
    [1, 1, 2, 2]
    

    (单下划线 _ 是 Python 中的有效变量名 (identifier),此处仅用于显示它实际上并未使用。它有一个 special meaning in interactive mode

    可以将它用于附加条件表达式,但没有实际用途:

    >>> [i for i in range(3)]
    [0, 1, 2]
    >>> [i for i in range(3) if i]
    [1, 2]
    >>> [i for i in range(3) if (True if i else False)]
    [1, 2]
    

    理解也可以嵌套创建“多维”列表(“数组”):

    >>> [[i for j in range(i)] for i in range(3)]
    [[], [1], [2, 2]]
    

    最后但并非最不重要的一点是,推导不仅限于创建list,即elseif 也可以在set 推导中以相同的方式使用:

    >>> {i for i in "set comprehension"}
    {'o', 'p', 'm', 'n', 'c', 'r', 'i', 't', 'h', 'e', 's', ' '}
    

    dictionary 理解:

    >>> {k:v for k,v in [("key","value"), ("dict","comprehension")]}
    {'key': 'value', 'dict': 'comprehension'}
    

    Generator Expressions 也使用相同的语法:

    >>> for g in ("a" if b else "c" for b in "generator"):
    ...     print(g, end="")
    ...
    aaaaaaaaa>>>
    

    可用于创建tuple (there is no tuple comprehension)。


    进一步阅读:

    【讨论】:

      【解决方案2】:

      很好的答案,但只是想提一个问题,即“pass”关键字在列表理解的 if/else 部分中不起作用(如上面提到的示例中所述)。

      #works
      list1 = [10, 20, 30, 40, 50]
      newlist2 = [x if x > 30 else x**2 for x in list1 ]
      print(newlist2, type(newlist2))
      
      #but this WONT work
      list1 = [10, 20, 30, 40, 50]
      newlist2 = [x if x > 30 else pass for x in list1 ]
      print(newlist2, type(newlist2))
      

      这是在 python 3.4 上尝试和测试的。 错误如下:

      newlist2 = [x if x > 30 else pass for x in list1 ]                                    
      SyntaxError: invalid syntax
      

      因此,请尽量避免列表推导中的 pass-es

      【讨论】:

      • 就列表理解而言,if/else 构造只是一个表达式。如果你想省略项目,你需要用你的表情代替expr2这里[expr1 for x in list1 if expr2]
      • Well pass 在正常的 if else 块中工作,对我来说,这意味着它也可以在其他任何地方工作。但在列表推导中并非如此。
      • 但这不是一个正常的 if/else 块。这是an expression。你也不能在那里使用 elif。
      【解决方案3】:

      要在 python 编程的列表推导中使用else,您可以尝试下面的 sn-p。这将解决您的问题,sn-p 在 python 2.7 和 python 3.5 上进行了测试。

      obj = ["Even" if i%2==0 else "Odd" for i in range(10)]
      

      【讨论】:

        【解决方案4】:

        另外,我认为列表推导是最有效的方法是否正确?

        也许吧。列表推导本质上不是计算效率高的。它仍在线性时间中运行。

        根据我的个人经验: 通过将列表推导(特别是嵌套推导)替换为上面的 for-loop/list-appending 类型结构,我在处理大型数据集时显着减少了计算时间。在这个应用程序中,我怀疑你会注意到差异。

        【讨论】:

        • 哎呀,我的意思是询问连接方法与字符串上的 +=。
        • 有趣。这 (wiki.python.org/moin/…) 另有说明。
        • @Josh:在旧版本的 Python 中,join() 方法要优越得多。较新版本的解释器试图优化 += 方法,但我不确定它的效果如何。我几乎总是只使用 join() 方法。
        【解决方案5】:

        语法a if b else c 是 Python 中的三元运算符,如果条件 b 为真,则计算结果为 a - 否则计算结果为 c。它可以用在理解语句中:

        >>> [a if a else 2 for a in [0,1,0,3]]
        [2, 1, 2, 3]
        

        所以对于你的例子,

        table = ''.join(chr(index) if index in ords_to_keep else replace_with
                        for index in xrange(15))
        

        【讨论】:

        • 请注意,这只适用于 Python 2.5 及更高版本。
        • 另请注意,else 是必需的,不能省略,因为始终需要结果值。
        • join() 中的代码,是没有括号时的列表理解吗?还是生成器表达式和连接将其作为参数就好了?
        • @huggie 这是一个生成器表达式,join 很乐意接受一个生成器或任何其他可迭代对象。
        【解决方案6】:

        如果你想要一个else,你不想过滤列表推导,你希望它遍历每个值。您可以改用true-value if cond else false-value 作为语句,并从末尾删除过滤器:

        table = ''.join(chr(index) if index in ords_to_keep else replace_with for index in xrange(15))
        

        【讨论】:

          猜你喜欢
          • 2022-01-12
          • 1970-01-01
          • 2020-02-29
          • 1970-01-01
          • 2011-05-23
          • 2018-07-06
          • 2020-11-24
          • 1970-01-01
          • 2021-10-13
          相关资源
          最近更新 更多