附加到多个For循环中的类列表

时间:2019-12-13 13:11:15

标签: python list class for-loop google-cloud-platform

在阅读了以下问题和各种答案("Least Astonishment" and the Mutable Default Argument)以及官方文档(https://docs.python.org/3/tutorial/controlflow.html#default-argument-values)之后,我编写了ResultsClass,以便其每个实例都有一个单独的列表而不影响默认值(至少,这是我从新获得的理解中应该发生的情况):

class ResultsClass:
    def __init__(self, 
    project = None, 
    badpolicynames = None, 
    nonconformpolicydisks = None, 
    diskswithoutpolicies = None, 
    dailydifferences = None, 
    weeklydifferences = None):
        self.project = project
        if badpolicynames is None:
            self.badpolicynames = []
        if nonconformpolicydisks is None:
            self.nonconformpolicydisks = []
        if diskswithoutpolicies is None:
            self.diskswithoutpolicies = []
        if dailydifferences is None:
            self.dailydifferences = []
        if weeklydifferences is None:
            self.weeklydifferences = []

这本身可以按预期工作:

i = 0
for result in results:
    result.diskswithoutpolicies.append("count is " + str(i))
    print(result.diskswithoutpolicies)
    i = i+1
['count is 0']
['count is 1']
['count is 2']
['count is 3']
etc.

此脚本的上下文是我正在尝试从Google Cloud基础架构中的每个项目中获取信息;在这种情况下,主要是具有与之关联的快照计划的磁盘列表,最近24小时内每个磁盘的计划快照列表,具有不符合我们的命名约定的不良计划名称的磁盘以及根本没有与之关联的任何快照计划。

在完整脚本中,我使用了完全相同的ResultsClass;但是在多个 for 循环中使用时,追加似乎又被添加到默认值中,老实说,我不明白为什么。 该代码的简化版本如下:

# Code to obtain a list of projects
results = [ResultsClass() for i in range((len(projects)))]
for result in results:
    for project in projects:
        result.project = project
        # Code to obtain each zone in the project
        for zone in zones:
            # Code to get each disk in zone
            for disk in disks:
                resourcepolicy = disk.get('resourcePolicies')
                    if resourcepolicy:
                        # Code to action if a resource policy exists 
                        else:
                            result.badpolicynames.append(resourcepolicy[0].split('/')[-1])
                            result.nonconformpolicydisks.append(disk['id'])
                    else:
                        result.diskswithoutpolicies.append(disk['id'])
        pprint(vars(result))

然后返回结果:

{'badpolicynames': [],
 'dailydifferences': None,
 'diskswithoutpolicies': ['**1098762112354315432**'],
 'nonconformpolicydisks': [],
 'project': '**project0**',
 'weeklydifferences': None}
{'badpolicynames': [],
 'dailydifferences': None,
 'diskswithoutpolicies': ['**1098762112354315432**'],
['**1031876156872354739**'],
 'nonconformpolicydisks': [],
 'project': '**project1**',
 'weeklydifferences': None}

一个 for 循环(或多个 for 循环)是否以某种方式否定了在ResultsClass中创建的单独列表?我需要了解为什么在Python中会发生这种情况,然后如何纠正它。

2 个答案:

答案 0 :(得分:2)

根据我的最佳理解,一个明显的问题是您要将结果和项目循环嵌套在一起,而您应该只循环其中的一个。我建议循环项目并在每个项目中创建一个result,而不是之前实例化list中的类。

results = []
for project in projects:
    result = ResultsClass(project)
    # Code to obtain each zone in the project
    for zone in zones:
        # Code to get each disk in zone
        for disk in disks:
            resourcepolicy = disk.get('resourcePolicies')
                if resourcepolicy:
                    # Code to action if a resource policy exists 
                    else:
                        result.badpolicynames.append(resourcepolicy[0].split('/')[-1])
                        result.nonconformpolicydisks.append(disk['id'])
                else:
                    result.diskswithoutpolicies.append(disk['id'])
    results.append(result)        
    pprint(vars(result))

这样,results是您的ResultsClass的列表,并且每个result仅包含一个一个项目,而您之前的尝试将以每个{ {1}}和最后一个相同的项目。

答案 1 :(得分:1)

我不确定我是否能正确地实现目标,但是您正在尝试将数据从每个项目传输到单个结果,对吧?

如果是这样,您可能希望使用zip在每个项目中获得单个结果:

for result, project in zip(results, projects):
   # rest of the code

否则,您将在下一个循环迭代中覆盖每个先前项目的结果。

另一种选择是在循环中创建结果:

results = []
for project in projects:
    result = ResultsClass()

    # ... your fetching code ...

    results.append(result)