【问题标题】:Appending To Class List Within Multiple For Loops在多个 For 循环中附加到类列表
【发布时间】:2019-12-13 13:11:15
【问题描述】:

在阅读了以下问题和各种答案 ("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.

这个脚本的上下文是我试图从我们的谷歌云基础设施中的每个项目中获取信息;在这种情况下,主要是与快照计划相关联的磁盘列表、过去 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 中会发生这种情况,以及如何纠正它。

【问题讨论】:

    标签: python list class for-loop


    【解决方案1】:

    根据我的最佳理解,一个明显的问题是您将结果和项目循环嵌套在一起,而您应该只循环其中任何一个。我建议循环项目并在每个项目中创建一个 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 仅包含一个 项目,而您之前的尝试将以每个ResultsClass 结束,最后一个项目。

    【讨论】:

    • 啊!非常感谢你!几个小时以来,我一直在为此挠头,试图弄清楚我到底做错了什么。你一针见血,并且解释得非常好。再次感谢!
    【解决方案2】:

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

    如果是这样,您可能希望使用 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)
    

    【讨论】:

    • 非常感谢!这两个答案最终都让我得到了正确的答案——我需要 results 是一个空列表,然后只有一个 for 循环而不是两个!我把事情复杂化了:)
    猜你喜欢
    • 2020-07-23
    • 2020-03-26
    • 2023-01-07
    • 2020-05-26
    • 2020-09-25
    • 1970-01-01
    • 1970-01-01
    • 2021-01-16
    • 2015-04-27
    相关资源
    最近更新 更多