【问题标题】:Single Line Nested For Loops单行嵌套 For 循环
【发布时间】:2013-06-05 02:11:17
【问题描述】:

在python中编写了这个转置矩阵的函数:

def transpose(m):
    height = len(m)
    width = len(m[0])
    return [ [ m[i][j] for i in range(0, height) ] for j in range(0, width) ]

在这个过程中,我意识到我并不完全理解单行嵌套 for 循环是如何执行的。请回答以下问题帮助我理解:

  1. 这个 for 循环的执行顺序是什么?
  2. 如果我有一个三重嵌套的 for 循环,它会执行什么顺序?
  3. 什么等于未嵌套的 for 循环?

给定,

[ function(i,j) for i,j in object ]
  1. 对象必须是什么类型才能使用此 for 循环结构?
  2. i 和 j 分配给 object 中的元素的顺序是什么?
  3. 可以用不同的for循环结构模拟吗?
  4. 这个 for 循环可以嵌套在类似或不同结构的 for 循环中吗?它会是什么样子?

我们也非常感谢您提供其他信息。

【问题讨论】:

    标签: python loops for-loop nested nested-loops


    【解决方案1】:

    最好的信息来源是official Python tutorial on list comprehensions。列表推导与 for 循环几乎相同(当然,任何列表推导都可以写成 for 循环),但它们通常比使用 for 循环更快。

    从教程中查看这个更长的列表推导(if 部分过滤推导,只有通过 if 语句的部分被传递到列表推导的最后部分(此处为 (x,y)):

    >>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
    [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
    

    这与这个嵌套的 for 循环完全相同(并且,正如教程所说,请注意 for 和 if 的顺序如何相同)。

    >>> combs = []
    >>> for x in [1,2,3]:
    ...     for y in [3,1,4]:
    ...         if x != y:
    ...             combs.append((x, y))
    ...
    >>> combs
    [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
    

    列表推导式和 for 循环之间的主要区别是 for 循环的最后部分(您在其中执行某项操作)位于开头而不是结尾。

    关于您的问题:

    对象必须是什么类型才能使用这个for循环结构?

    iterable。可以生成(有限)一组元素的任何对象。这些包括任何容器、列表、集合、生成器等。

    i 和 j 分配给 object 中的元素的顺序是什么?

    它们的分配顺序与从每个列表生成的顺序完全相同,就好像它们在嵌套的 for 循环中一样(对于您的第一个理解,您将获得 i 的 1 个元素,然后是 j 的每个值,第二个元素进入 i,然后来自 j 的每个值,等等)

    可以用不同的for循环结构模拟吗?

    是的,上面已经显示了。

    这个 for 循环可以嵌套在类似或不同结构的 for 循环中吗?它会是什么样子?

    当然可以,但这不是一个好主意。例如,这里给你一个字符列表:

    [[ch for ch in word] for word in ("apple", "banana", "pear", "the", "hello")]
    

    【讨论】:

    • 我想知道是什么引导了他们在双重嵌套中选择排序。我发现另一种方式更自然(在您的示例中,对于 y 然后对于 x )。我只是意识到,在做了 3 年的 Python(不是广泛但仍然......)和使用这些循环之后!
    • @Thomas 我还发现另一种方式更直观。我认为选择纯粹是为了方便。以更直观的方式进行操作意味着必须处理未解析的符号,直到稍后在语句中找到它们。尝试在纸上为每个城市的每个 city.bananastore 解析每个香蕉中的每个香蕉.peel。没那么容易。不过反过来,又好又容易。
    【解决方案2】:

    首先,您的第一个代码本身不使用 for 循环,而是使用 list comprehension

    1. 相当于

      对于范围内的 j(0,宽度): 对于范围内的 i(0,高度): m[i][j]

    2. 同样的方式,它通常像 for 循环一样嵌套,从右到左。但列表推导语法更复杂。

    3. 我不确定这个问题在问什么


    1. 任何产生恰好产生两个对象的可迭代对象的可迭代对象(多么拗口 - 即[(1,2),'ab'] 将是有效的)

    2. 对象在迭代时产生的顺序。 i 进入第一个产量,j 第二个。

    3. 是的,但没有那么漂亮。我相信它在功能上等同于:

      l = 列表() 对于对象中的 i,j: l.append(函数(i,j))

      或者更好地使用map:

      map(function, object)
      

      当然,函数必须得到ij 本身。

    4. 这和3不是同一个问题吗?

    【讨论】:

    • Guido,python 的创造者,非常反对使用 map,以至于他考虑从 python 中删除它
    【解决方案3】:

    您可能对itertools.product 感兴趣,它从您传递的所有可迭代对象中返回一个可迭代的产生值的元组。也就是说,itertools.product(A, B) 产生(a, b) 形式的所有值,其中a 值来自Ab 值来自B。例如:

    import itertools
    
    A = [50, 60, 70]
    B = [0.1, 0.2, 0.3, 0.4]
    
    print [a + b for a, b in itertools.product(A, B)]
    

    打印出来:

    [50.1, 50.2, 50.3, 50.4, 60.1, 60.2, 60.3, 60.4, 70.1, 70.2, 70.3, 70.4]
    

    注意传递给itertools.product 的最后一个参数是“内部”参数。一般itertools.product(a<sub>0</sub>, a<sub>1</sub>, ... a<sub>n</sub>)等于[(i<sub>0</sub>, i<sub>1</sub>, ... i<sub>n</sub>) for i<sub>n</sub> in a<sub>n</sub> for i<sub>n-1</sub> in a<sub>n-1</sub> ... for i<sub>0</sub> in a<sub>0</sub>]

    【讨论】:

      【解决方案4】:

      下面的代码是嵌套循环的最佳示例,当使用两个 for 循环时,请记住第一个循环的输出是第二个循环的输入。 使用嵌套循环时,循环终止也很重要

      for x in range(1, 10, 1):
           for y in range(1,x):
                   print y,
              print
      OutPut :
      1
      1 2
      1 2 3
      1 2 3 4
      1 2 3 4 5
      1 2 3 4 5 6
      1 2 3 4 5 6 7
      1 2 3 4 5 6 7 8
      

      【讨论】:

        【解决方案5】:

        您可以使用zip 函数在同一行中使用两个 for 循环

        代码:

        list1 = ['Abbas', 'Ali', 'Usman']
        list2 = ['Kamran', 'Asgar', 'Hamza', 'Umer']
        list3 = []
        for i,j in zip(list1,list2):
            list3.append(i)
            list3.append(j)
        print(list3)
        

        输出:

        ['Abbas', 'Kamran', 'Ali', 'Asgar', 'Usman', 'Hamza']

        因此,通过使用 zip 函数,我们可以使用两个 for 循环,或者我们可以在同一行中迭代两个列表。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-04-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多