Python中dict变量for循环的神奇行为

2024-10-03 21:33:11 发布

您现在位置:Python中文网/ 问答频道 /正文

初级python程序员在这里和我一直在敲打我的头对砖墙意外的for循环和字典行为。我在一个CSV日志文件中循环,并将数据解析为一个categories dict。每次通过循环初始化categories dict时,它都能正常工作。。你知道吗

像这样:

log_entries = AutoVivification()
# http://stackoverflow.com/questions/635483/what-is-the-best-way-to-implement-nested-dictionaries-in-python

def scrublooper(log_file):

    for ll in log_file:
    # Initialize  categories dict every round through the loop
    categories = {'requests': {'Content_Visual': 0, 'Content_ProgramsUpdates': 0, 'Content_Text': 0, 'Pages': 0, 'Content_Files': 0}, 'filter_action': {'re': 0, 'pl': 0, 'bs': 0}}
    lld = LogDomain(ll)
    domain, hostname, lan_host = lld.domain, lld.hostname, lld.lan_host


    mimetypes = url_searcher(Settings.mimetypes, lld.mime_type)

    if mimetypes:
        category = mimetypes[2]

        if not log_entries[lan_host].has_key(domain): 
            log_entries[lan_host][domain]= categories

        log_entries[lan_host][domain]['requests'][category] += 1 

print log_entries['192.168.5.210']['google.com']['requests']
print log_entries['192.168.5.210']['webtrendslive.com']['requests']
print log_entries['192.168.5.210']['osnews.com']['requests']
print log_entries['192.168.5.210']['question-defense.com']['requests']
print log_entries['192.168.5.210']['optimost.com']['requests']

这个外观的输出是我所期望的:

{'Content_Visual': 0, 'Content_ProgramsUpdates': 0, 'Content_Text': 95, 'Pages': 0, 'Content_Files': 0}
{'Content_Visual': 0, 'Content_ProgramsUpdates': 0, 'Content_Text': 1, 'Pages': 0, 'Content_Files': 0}
{'Content_Visual': 0, 'Content_ProgramsUpdates': 0, 'Content_Text': 2, 'Pages': 0, 'Content_Files': 0}
{'Content_Visual': 0, 'Content_ProgramsUpdates': 0, 'Content_Text': 18, 'Pages': 0, 'Content_Files': 0}
{'Content_Visual': 0, 'Content_ProgramsUpdates': 0, 'Content_Text': 3, 'Pages': 0, 'Content_Files': 0}

但是!这是我的问题。我不想每次通过循环都初始化categories dict。在这个简化的例子中,这无关紧要,但是在这个程序的开发过程中,它会导致性能显著下降(30%)。你知道吗

我需要初始化一次目录:

log_entries = AutoVivification()
categories = {'requests': {'Content_Visual': 0, 'Content_ProgramsUpdates': 0, 'Content_Text': 0, 'Pages': 0, 'Content_Files': 0}, 'filter_action': {'re': 0, 'pl': 0, 'bs': 0}}

def scrublooper(log_file):

    for ll in log_file:
    lld = LogDomain(ll)
    # etc, etc, etc

但是,当我在for循环之外的任何地方初始化categories dict时(无论是在scrublooper函数中还是仅仅在log\u entries变量之后),输出是:

{'Content_Visual': 0, 'Content_ProgramsUpdates': 0, 'Content_Text': 685, 'Pages': 0, 'Content_Files': 0}
{'Content_Visual': 0, 'Content_ProgramsUpdates': 0, 'Content_Text': 685, 'Pages': 0, 'Content_Files': 0}
{'Content_Visual': 0, 'Content_ProgramsUpdates': 0, 'Content_Text': 685, 'Pages': 0, 'Content_Files': 0}
{'Content_Visual': 0, 'Content_ProgramsUpdates': 0, 'Content_Text': 685, 'Pages': 0, 'Content_Files': 0}
{'Content_Visual': 0, 'Content_ProgramsUpdates': 0, 'Content_Text': 685, 'Pages': 0, 'Content_Files': 0}

所有“内容文本”值的增量相等!这里发生了什么?我肯定我违反了python的一些原则,但不知道该怎么做。我花了好几个小时才弄明白这个问题与分类有关

非常感谢您的解释。你知道吗


Tags: textcomlogdomainfilespagescontentrequests
1条回答
网友
1楼 · 发布于 2024-10-03 21:33:11

我不熟悉您正在使用的工具,但是当您在循环之外创建字典时,您只是在创建一个字典。你知道吗

if not log_entries[lan_host].has_key(domain): 
        log_entries[lan_host][domain]= categories

这段代码只是使日志条目[lan\u host][domain]指向单个字典。Python不会复制值之类的东西。所以这几行指的是同一本词典。你知道吗

log_entries['192.168.5.210']['google.com']
log_entries['192.168.5.210']['webtrendslive.com']

另外,我不能肯定,但我的直觉告诉我,不想为了性能而初始化一个新字典可能太过分了。你知道吗

相关问题 更多 >