【问题标题】:Convert Pythonic approach of looping into nested loops将 Pythonic 的循环方法转换为嵌套循环
【发布时间】:2017-09-13 12:41:26
【问题描述】:

我是 Python 的初学者。我想了解循环的 Pythonic 方法,因为我长期以来一直是 C 编码器。给定以下两行:

{k: v for out_d in outs for k, v in out_d.iteritems()}
[{} for i in range(nthreads)]

有人可以分解它,使其遵循嵌套循环的 C 标准方法吗?

【问题讨论】:

    标签: python python-2.7 loops nested-loops python-2.x


    【解决方案1】:
    my_dict = {k: v for out_d in outs for k, v in out_d.iteritems()}
    
    # is equivalent to
    
    my_dict = {}
    for out_d in outs:
        for key, value in out_d.iteritems():
            my_dict[key] = value
    
    
    
    my_list = [{} for i in range(nthreads)]
    
    # is equivalent to
    
    my_list = []
    for i in range(nthreads):
        my_list.append({})
    

    【讨论】:

      【解决方案2】:
      for key, value in out_d.iteritems()
      

      -- iteritems() 循环遍历字典的键/值,所以 out_d 必须是字典

      for out_d in outs
      

      -- for out_d in outs 将循环遍历outs 中的迭代器,基于前面我们可以假设这是一个字典列表

      {k:v}
      

      -- 这将使用 k、v 的值创建一个新的字典理解

      大家一起:

      为每个键、字典 out_d 中的值、列表 outs 中的每个 out_d 创建值 k、v 的字典理解

      new_dict = {}
      for dictionary in outs:
          for key, value in dictionary.iteritems()
              new_dict[key] = value
      

      【讨论】:

        【解决方案3】:

        等价物是:

        res = {}
        for out_d in outs:
            for k, v in out_d.iteritems():
                res[k] = v
        
        res = []
        for i in range(nthreads):
            res.append({})
        

        请注意,您可以通过使用不同的缩进自己相对简单地找到这些:

        {k: v for out_d in outs for k, v in out_d.iteritems()}
        
        =>
        
        {k: v 
         for out_d in outs 
         for k, v in out_d.iteritems()}
        
        =>
        
        {        k: v 
         for out_d in outs 
             for k, v in out_d.iteritems()}
        

        唯一棘手的一点是第一个语句k: v 实际上在最内层循环中,但所有后面的表达式都按“循环”等效项的顺序排序。此外,根据理解的类型,第一个语句会有所不同。

        对于dict-comprehensions,它是the_dict[key] = value,而不是key: value,对于列表理解,它是the_list.append(value),对于set-comprehensions,它是the_set.add(value)。生成器表达式更复杂,因为您必须编写一个 yield value 的函数。

        【讨论】:

          【解决方案4】:

          Python:列表理解

          Python 支持称为“列表推导”的概念。它可以用来以非常自然、简单的方式构建列表,就像数学家习惯做的那样。

          以下是数学中描述列表(或集合、元组或向量)的常用方法。

          S = {x² : x in {0 ... 9}}
          V = (1, 2, 4, 8, ..., 2¹²)
          M = {x | x in S and x even}
          

          您可能从学校的数学课中知道上述内容。在 Python 中,您几乎可以像数学家一样编写这些表达式,而无需记住任何特殊的神秘语法。

          这就是您在 Python 中执行上述操作的方式:

          >>> S = [x**2 for x in range(10)]
          >>> V = [2**i for i in range(13)]
          >>> M = [x for x in S if x % 2 == 0]
          >>> 
          >>> print S; print V; print M
          [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
          [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096]
          [0, 4, 16, 36, 64]
          

          我确定你想看一个更复杂的例子。 :-) 下面是另一种计算素数的方法。有趣的是,我们首先构建了一个非素数列表,使用单个列表推导,然后使用另一个列表推导得到列表的“逆”,即质数。

          >>> noprimes = [j for i in range(2, 8) for j in range(i*2, 50, i)]
          >>> primes = [x for x in range(2, 50) if x not in noprimes]
          >>> print primes
          [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
          

          注意:您可以将列表推导式嵌套在彼此之间,因此您可以使用单个语句编写上述示例(不需要临时变量“noprimes”)。但是,这样的行往往会变得很长且可读性较差,因此不建议这样做。

          当然,列表推导不仅适用于数字。列表可以包含任何类型的元素,包括字符串、嵌套列表和函数。您甚至可以在一个列表中混合不同的类型。

          以下处理字符串列表并生成列表列表。每个子列表包含两个字符串和一个整数。

          >>> words = 'The quick brown fox jumps over the lazy dog'.split()
          >>> print words
          ['The', 'quick', 'brown', 'fox', 'jumps', 'over', 'the', 'lazy', 'dog']
          >>> 
          >>> stuff = [[w.upper(), w.lower(), len(w)] for w in words]
          >>> for i in stuff:
          ...     print i
          ... 
          ['THE', 'the', 3]
          ['QUICK', 'quick', 5]
          ['BROWN', 'brown', 5]
          ['FOX', 'fox', 3]
          ['JUMPS', 'jumps', 5]
          ['OVER', 'over', 4]
          ['THE', 'the', 3]
          ['LAZY', 'lazy', 4]
          ['DOG', 'dog', 3]
          >>> 
          >>> stuff = map(lambda w: [w.upper(), w.lower(), len(w)], words)
          >>> for i in stuff:
          ...     print i
          ... 
          ['THE', 'the', 3]
          ['QUICK', 'quick', 5]
          ['BROWN', 'brown', 5]
          ['FOX', 'fox', 3]
          ['JUMPS', 'jumps', 5]
          ['OVER', 'over', 4]
          ['THE', 'the', 3]
          ['LAZY', 'lazy', 4]
          ['DOG', 'dog', 3]
          

          上面的例子也证明了你可以用 map() 和一个 lambda 函数做同样的事情。但是,在某些情况下,您不能使用 map() 而必须使用列表推导,反之亦然。当您可以同时使用这两种方法时,通常最好使用列表推导式,因为大多数情况下这样更有效且更易于阅读。

          当构造规则过于复杂而无法用“for”和“if”语句表达时,或者构造规则可以在运行时动态更改时,您不能使用列表推导式。在这种情况下,您最好将 map() 和/或 filter() 与适当的函数一起使用。当然,您可以将其与列表推导结合使用。

          【讨论】:

            猜你喜欢
            • 2021-12-30
            • 1970-01-01
            • 2016-04-24
            • 2012-11-06
            • 1970-01-01
            • 2013-11-29
            • 2020-11-26
            • 2011-06-07
            • 2019-11-22
            相关资源
            最近更新 更多