【问题标题】:Python: copying a repeating dictionary into a list - last dict item being duped to all list itemsPython:将重复字典复制到列表中-最后一个字典项被复制到所有列表项
【发布时间】:2013-02-19 11:14:00
【问题描述】:

考虑以下几点:

import re
sequence = 'FFFFFF{7}FFFFFF'
patterns = [ ('([0-9a-fA-F]+)', 'Sequence'),
    ('(\\([0-9a-fA-F]+\\|[0-9a-fA-F]+\\))', 'Option'),
    ('({[0-9a-fA-F]+})', 'Range'),
    ('(\\[[0-9a-fA-F]+:([0-9a-fA-F]+|\*)\\])', 'Slice'),
    ('(\\?\\?)+', 'Byte_value_Wildcard'),
    ('(\\*)+', 'Byte_length_wildcard') ]
fragment_counter = 0
fragment_dict= {}
fragments_list = []
while sequence:
    found = False
    for pattern, name in patterns:
        m = re.match (pattern,sequence)
        if m:
            fragment_counter+=1
            m = m.groups () [0]
            fragment_dict["index"]=fragment_counter
            fragment_dict["fragment_type"]=name
            fragment_dict["value"]=m
            print fragment_dict
            fragments_list.append(fragment_dict)
            sequence = sequence [len (m):]
            found = True
            break
     if not found: raise Exception ('Unrecognized sequence')

print fragments_list

每次点击“print fragment_dict”行时,我都会得到正确的(预期的)输出:

{'index': 1, 'fragment_type': 'Sequence', 'value': 'FFFFFF'}
{'index': 2, 'fragment_type': 'Range', 'value': '{7}'}
{'index': 3, 'fragment_type': 'Sequence', 'value': 'FFFFFF'}

但是,列表项fragments_list 是最终字典的 3 个副本,而不是我期望的每一行:

[{'index': 3, 'fragment_type': 'Sequence', 'value': 'FFFFFF'}, {'index': 3, 'fragment_type': 'Sequence', 'value': 'FFFFFF'}, {'index': 3, 'fragment_type': 'Sequence', 'value': 'FFFFFF'}]

我假设这是因为append 引用了字典的实例,而不是复制字典的每次迭代。我查看了使用 list() 函数,但在 dict 项上它只是给了我一个 dict 键的列表。

我做错了什么?
我并不拘泥于数据类型,我只需要一种方法来为我找到的每个片段保存 3 个数据元素(也许是第 4 个)。

【问题讨论】:

    标签: python list dictionary


    【解决方案1】:

    你很亲密。而不是 list() 函数,它从任何序列生成一个新的 list(在这种情况下,一个 dict 作为一个序列是它的键序列),使用 dict() 函数,它生成一个新的 @ 987654325@ 来自任何映射。

    或者,也许更简单,只需使用copy 方法。

    或者,更简单地说,只需将fragment_dict= {} 移动到循环中,这样您就可以构建一个新的dict,而不是继续重复使用相同的dict。

    【讨论】:

    • 如此简单。事实上,我应该刚刚测试过dict!谢谢你。赞赏。
    • @JayGattuso:这种事情一旦你知道就很明显,但在你知道之前就不那么明显了……
    【解决方案2】:

    很高兴看到您实际上使用的是我对您上一个问题的回答的代码。当我的回答确实有帮助时,我总是很高兴。

    考虑到,在您之前的问题中,您表示此解析只是之后处理已解析令牌的热身,您可能会考虑这样:

    为您拥有的每种令牌类型创建一个类。在其中的每一个内部实现一个process 方法,它有时会进行实际处理(而不是我在下面的代码中执行的 wolfing、bearing、foxing 和 badgering)。

    然后使用 Stream 类解析整个流。您可以通过Stream.tokens 对令牌进行迭代,并且您可以通过调用Stream.process 处理包含的所有令牌。

    您将这些类放在一个 python 文件中,将其导入您的主代码中,您只需要创建一个 Stream 的实例来解析和处理它。

    类似这样的:

    #! /usr/bin/python3.2
    
    import re
    
    class Sequence:
        def __init__ (self, raw): self.__raw = raw
        def __str__ (self): return 'Sequence {}'.format (self.__raw)
        def process (self): print ('Wolfing sequence {}'.format (self.__raw) )
    
    class Option:
        def __init__ (self, raw): self.__raw = raw
        def __str__ (self): return 'Option {}'.format (self.__raw)
        def process (self): print ('Foxing option {}'.format (self.__raw) )
    
    class Range:
        def __init__ (self, raw): self.__raw = raw
        def __str__ (self): return 'Range {}'.format (self.__raw)
        def process (self): print ('Bearing range {}'.format (self.__raw) )
    
    class Slice:
        def __init__ (self, raw): self.__raw = raw
        def __str__ (self): return 'Slice {}'.format (self.__raw)
        def process (self): print ('Badgering slice {}'.format (self.__raw) )
    
    
    class Stream:
        patterns = [ ('([0-9a-fA-F]+)', Sequence),
            ('(\\([0-9a-fA-F]+\\|[0-9a-fA-F]+\\))', Option),
            ('({[0-9a-fA-F]+})', Range),
            ('(\\[[0-9a-fA-F]+:[0-9a-fA-F]+\\])', Slice) ]
    
        def __init__ (self, stream):
            self.__tokens = []
            while stream:
                found = False
                for pattern, cls in self.patterns:
                    m = re.match (pattern, stream)
                    if m:
                        m = m.groups () [0]
                        self.__tokens.append (cls (m) )
                        stream = stream [len (m):]
                        found = True
                        break
                if not found: raise Exception ('Unrecognized sequence')
    
        @property
        def tokens (self): return (token for token in self.__tokens)
    
        def process (self):
            for token in self.__tokens: token.process ()
    
    stream = Stream ('524946(46|58){4}434452[22:33]367672736E')
    print ('These are the tokens:')
    for idx, token in enumerate (stream.tokens):
        print ('{} at position {}.'.format (token, idx) )
    
    print ('\nNow let\'s process them all:')
    stream.process ()
    

    这会产生:

    These are the tokens:
    Sequence 524946 at position 0.
    Option (46|58) at position 1.
    Range {4} at position 2.
    Sequence 434452 at position 3.
    Slice [22:33] at position 4.
    Sequence 367672736E at position 5.
    
    Now let's process them all:
    Wolfing sequence 524946
    Foxing option (46|58)
    Bearing range {4}
    Wolfing sequence 434452
    Badgering slice [22:33]
    Wolfing sequence 367672736E
    

    【讨论】:

    • 嘿,这太棒了,谢谢!我的下一个砖墙面向我,我怀疑您修改后的方法将帮助我适当地导航结果数据对象。我将实现,然后看看我能做什么,但基本上下一个任务是能够根据一些逻辑提取每个序列的片段实体 - (例如,哪个片段实体具有最大的 len() 以及它的索引是多少)。我相信我很快就会回来提问,但再次感谢您的意见,它非常有用!既要解决手头的问题,又要看看有经验的用户如何解决问题!
    • 这可能与这里的工作方式非常矛盾,但我想再次感谢您的帮助。花了一些时间把它放在一起,你的代码是完美的,所以很容易(1)看到发生了什么和(2)使用。它的表现与我想象的完全一样。我非常感激!
    • 不客气,我很乐意为您提供帮助。一旦你准备好了,我也很乐意对你的代码进行同行评审。一个人总是可以互相学习一点。不幸的是,SO 不允许私人消息,但如果您可以在此处留下电子邮件地址,我会与您联系,以防您希望同行评审。
    • 这是一个非常好的提议,谢谢!我很感激。您可以通过 dia dot govt dot nz 的 jay.gattuso 与我联系。关于与您的代码生成的数据结构进行交互,我确实有一大堆问题——您希望我通过 SO 还是通过电子邮件问他们?
    • 由你决定,在如此多的时间里,更多的人可以从中受益,你也会获得更多的观点。如果这是非常专业的事情,请不要怀疑与我联系。我刚刚给你发了一封邮件。
    猜你喜欢
    • 2022-11-30
    • 2020-11-25
    • 2010-11-20
    • 2017-11-27
    • 1970-01-01
    • 2013-12-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-31
    相关资源
    最近更新 更多