Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/reporting-services/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使嵌套for循环更加Pythonic_Python_List Comprehension_Nested Loops - Fatal编程技术网

如何使嵌套for循环更加Pythonic

如何使嵌套for循环更加Pythonic,python,list-comprehension,nested-loops,Python,List Comprehension,Nested Loops,我必须为每个密钥创建一个被阻止用户的列表。每个用户都有多个属性,如果这些属性中的任何一个在键中,则该用户将被阻止 我为-loop编写了以下嵌套的,它对我很有用,但我想用一种更具pythonic风格的方式编写它,用更少的行和更具可读性的方式。我该怎么做 for key in keys: key.blocked_users = [] for user in get_users(): for attribute in user.attributes: for key

我必须为每个密钥创建一个被阻止用户的列表。每个用户都有多个属性,如果这些属性中的任何一个在键中,则该用户将被阻止

我为-loop编写了以下嵌套的
,它对我很有用,但我想用一种更具pythonic风格的方式编写它,用更少的行和更具可读性的方式。我该怎么做

for key in keys:
    key.blocked_users = []

for user in get_users():
    for attribute in user.attributes:
        for key in keys:
            if attribute.name == key.name:
                key.blocked_users.append(user)

尝试在列表理解中使用listed for循环,如果这被认为更像python,比如:

[key.blocked_users.append(user) for key in keys 
        for attribute in user.attributes 
        for user in get_users() 
        if attribute.name == key.name]

您可以在第一个
for
-循环中使用条件理解:

for key in keys:
    keyname = key.name
    key.blocked_users = [user for user in get_users() if any(attribute.name == keyname for attribute in user)]

在您的特定情况下,如果内部
for
循环依赖于外部循环变量,我会让代码保持原样。通过强制减少行数并不会使代码更具python风格或可读性

如果这些嵌套循环是直观编写的,那么它们可能很容易阅读

如果您为
循环嵌套了带有“独立”循环变量的
,则可以使用
itertools.product
。下面是一个演示:

>>> from itertools import product
>>> a = [1, 2]
>>> b = [3, 4]
>>> c = [5]
>>> for x in product(a, b, c): x
... 
(1, 3, 5)
(1, 4, 5)
(2, 3, 5)
(2, 4, 5)

除了使其更短之外,您还可以尝试将操作简化为在Python中优化的函数。它可能不会更短,但可能会更快——还有什么比速度更像蟒蛇呢?:)

例如,迭代每个用户的每个属性的键。这需要“远离”进行优化。例如,您可以在字典(用于查找)和集合(用于与属性名的交集)中收集一次键名:

set(keyname\u-map)
是一个非常有效的操作,因此保留两个集合并不重要

然后使用
set.intersection
获取与属性名称匹配的键名:

for user in get_users():
    for key in keynames.intersection({attribute.name for attribute in user.attributes}):
        keyname_map[key].append(user)
set.intersection
也很快


但是,这种方法要求您的
属性.name
s和
键.name
s是可散列的。

我不认为这更具可读性。当你把行包装成80个字符时,它甚至不会短很多。我不确定像这样长的列表理解是否真的更可读。而且使用
列表
理解副作用似乎是一种滥用。我不认为你的代码是不和谐的。我也不认为保存行必然会使代码更具python风格。无论如何:通常可以使用
itertools.product
来“避免”嵌套for循环,但如果内部循环依赖于外部循环变量,则不能这样做。这看起来很好。在列表理解中为
循环使用3
,这简直是一团糟。正如我写的那样,如果这是一个昂贵的操作,它会从循环中拉出
users=get\u users()
。我没有创建
keyname
,但这只是一个小小的性能改进。同意,使用
itertools.product(get_users(),keys)
仍然会留下一个笨拙的
键。阻止了用户的创建。@AChampion正如我所说的,我不建议在OP的情况下使用
itertools.product
。对不起,这是一个协议。
for user in get_users():
    for key in keynames.intersection({attribute.name for attribute in user.attributes}):
        keyname_map[key].append(user)