初级python程序员在这里,我一直在针对意外的循环和字典行为打砖墙。我循环遍历日志条目的CSV文件并将数据解析为类别dict。当我每次通过循环初始化类别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}
无论其!这是我的问题。我不希望每次循环都初始化类别dict。在这个简化的示例中,它并不重要,但是在此计划的实施过程中,它将导致性能显着下降(30%)。
我需要初始化类别dict ONCE:
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循环之外初始化类别dict ANWWHERE时(无论是在scrublooper函数中还是在log_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}
所有'Conent_Text'值均匀增加!这里发生了什么?我确定我违反了一些python原则,但不知道是什么或怎么找出来。我花了几个小时才弄清楚问题与类别字典有关。
很有必要解释。
答案 0 :(得分:2)
我不熟悉你正在使用的工具,但是当你在循环之外创建字典时,你只是创建一个字典。
if not log_entries[lan_host].has_key(domain):
log_entries[lan_host][domain]= categories
此代码只是使log_entries [lan_host] [domain]指向该单个字典。 Python不会复制值或类似的东西。所以这些行指的是同一个字典。
log_entries['192.168.5.210']['google.com']
log_entries['192.168.5.210']['webtrendslive.com']
P.S。我不能肯定地说,但我的直觉说不想初始化一本新词典的表现可能是过分的。