【问题标题】:Iterating over a dictionary while iterating a dictionary list in Python在 Python 中迭代字典列表时迭代字典
【发布时间】:2016-02-25 20:54:15
【问题描述】:

我正在编写一个程序,需要使用此函数将依赖项添加到 xml 文件。这段代码有效,但我想问一下是否有更 Pythonic 的方式来做到这一点。

我相信我以非 Python 方式做的部分是嵌套的 for 循环。有没有更好的方法来迭代字典列表和每个值?

def add_Dependencies(self):
        """ Adds the dependencies in a feature using dictionaries. When
            a feature is loaded, its dependencies are added to 
            dictionaries. Three for each type of software that the 
            dependencies are categorized as."""

        dependency_dict_list = [
            self.os_dict, self.visual_dict, self.audio_dict
            ]   

        dependencies = self.dependencies
        for dictionary in dependency_dict_list:                                                
            for feature, software in dictionary.items():                                            
                if all(dependency.text != feature for dependency in dependencies):
                    etree.SubElement(dependencies,"Dependency", Software = software).text = feature  

【问题讨论】:

  • 对于嵌套的 for 循环,绝对没有什么不合情理的。如果您愿意,可以重构您的代码以使用理解,但由于最里面的语句是有副作用的,并且不打算返回一个值,因此例如不明智的做法是将它包装在 lambda 或其他东西中,以便它可以在理解中出现。我相信您使用循环的方法是干净、良好、易于阅读的代码,而且它可能不是很好地利用时间来制作所谓的“pythonic”。
  • self.dependencies 在调用此函数之前是否为空?如果您首先将多个字典合并在一起(使用具有 O(1) 键查找的数据结构),然后仅创建 XML 元素,那么您的代码似乎会更快。
  • @Blckknght self.dependencies 将是一个 lxml 对象(应该已指定。)依赖项中的依赖项是子项。我会调查的。
  • @Mr.F 感谢您的反馈。
  • @Mr.F 我很高兴听到一位更有经验的 python 用户说,列出理解所有的东西并不总是最 Python 的方式。就个人而言,10 个示例中有 9 个我仍然觉得没有它们更清晰、更容易理解更冗长的代码。

标签: python python-3.x dictionary


【解决方案1】:

您可以使用collections.ChainMap 将您的三个字典合并为一个类似字典的映射。或者,由于您不关心这些值,您可以将它们的键合并到 set

使用它来避免嵌套循环并不是很重要。嵌套循环可以是完美的 Pythonic,但如果嵌套太深,您可能希望将一些内部位分解到函数中。

您可能想要在此处使用ChainMapset 的真正原因是避免O(N**2) 搜索XML 树以消除重复依赖项的运行时复杂性。他们还消除了嵌套级别是一个次要的好处。

试试这样的:

new_dependencies = (set(self.os_dict).union(self.visual_dict, self.audio_dict) -
                    set(dependency.text for dependency in self.dependencies))

for feature in new_dependencies:
   etree.SubElement(self.dependencies,"Dependency", Software = software).text = feature 

【讨论】:

    【解决方案2】:

    老实说,这根本没有错。如果您有兴趣,我会将其放在一起,它应该会更快一些,并且不那么冗长。我剪掉了嵌套的 for 循环并将 all 翻转为 any(它对我来说读起来更清晰,但这真的只是味道)。

    all_dependencies = dict(self.os_dist, **self.visual_dict)
    all_dependencies.update(self.audio_dict)
    
    for feature, software in dictionary.items():
        if not any(dependency.text == feature for dependency in dependencies):
            etree.SubElement(dependencies,"Dependency", Software = software).text = feature
    

    【讨论】:

    • 您能解释一下第一行的工作原理吗?如果不会太麻烦。当尝试在 IDLE 上执行类似的操作以查看其工作原理时,我收到一条错误消息。
    • dict.update() 返回None,因此您的all_dependencies 将是None
    • 我看到你更改了代码,但 python shell 说 dict 最多需要 1 个参数。
    • 我在使用手机时打错了字,但刚刚改正。它现在应该可以通过将 2 个字典连接成一个字典(这是我所知道的组合 2 个字典的最快方式,并且迭代大型字典要快得多)与第 2 个字典作为 kwarg
    • 这也有帮助。谢谢!
    猜你喜欢
    • 2014-09-26
    • 2013-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-28
    • 2012-09-01
    • 1970-01-01
    相关资源
    最近更新 更多