将Pythonic循环方法转换为嵌套循环

问题描述 投票:2回答:4

我是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
4个回答
2
投票
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({})

1
投票
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创建字典out_d中每个键,值的值k,v的字典理解

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

1
投票

等价物是:

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实际上位于最内层循环中,但所有后面的表达式都按照“loopy”等价的顺序排序。根据理解的类型,第一个陈述也会有所不同。

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


0
投票

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()与适当的函数一起使用。当然,您可以将其与列表推导相结合。

© www.soinside.com 2019 - 2024. All rights reserved.