单行嵌套循环


102

在转置矩阵的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) ]

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

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

鉴于

[ function(i,j) for i,j in object ]
  1. 为了将其用于循环结构,对象必须是哪种类型?
  2. 将i和j分配给object中的元素的顺序是什么?
  3. 可以用不同的for循环结构模拟吗?
  4. 可以将此for循环嵌套在相似或不同的for循环结构中吗?看起来如何?

附加信息也将不胜感激。

Answers:


169

最好的信息来源是有关列表理解官方Python教程。列表理解与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循环的最后部分(您在其中进行操作)始于而不是结束。

关于您的问题:

为了将其用于循环结构,对象必须是哪种类型?

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

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

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

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

是的,上面已经显示了。

可以将此for循环嵌套在相似或不同的for循环结构中吗?看起来如何?

是的,但这不是一个好主意。例如,在此处为您提供字符列表:

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

我想知道是什么引导了他们在双重嵌套中选择顺序。我发现另一种更自然的方式(在您的示例中,对于y然后对于x)。我只是意识到经过3年(不是广泛使用python还是使用python循环)!
托马斯

@Thomas我也发现另一种更直观的方式。我认为选择纯粹是为了方便。以更直观的方式进行操作将意味着必须处理未解析的符号,直到在语句的后面找到它们为止。尝试在纸上解析每个banana中每个banana.bananastore中每个banana中的每个banana.peel。不那么容易。相反,又好又容易。
平壤

29

您可能对感兴趣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(a0, a1, ... an)[(i0, i1, ... in) for in in an for in-1 in an-1 ... for i0 in a0]


4

首先,您的第一个代码本身并不使用for循环,而是使用列表推导

  1. 相当于

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

  2. 大致相同,它通常像for循环一样从右到左嵌套。但是列表理解语法更复杂。

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


  1. 产生可迭代对象且恰好产生两个对象的任何可迭代对象(实际上[(1,2),'ab']是有效的)

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

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

    l = list()
    对于对象中的i,j:
        l.append(function(i,j))
    

    甚至更好地使用map

    map(function, object)

    不过,当然功能必须得到ij本身。

  4. 这不是3个相同的问题吗?


2

您可以使用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循环,也可以迭代同一行中的两个列表。


-1

下面的代码提供了嵌套循环的最佳示例,同时使用两个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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.