简体   繁体   English

使用`defaultdicts`的Python程序无法正常工作

[英]Python program using `defaultdicts` doesn't work as expected

Expected result: 预期结果:

main_dict = { 
                'a':
                    { 0: 'Letter a',
                      1: 'Letter a',
                      2: 'Letter a',},

                'b':
                    { 0: 'Letter b',
                      1: 'Letter b',
                      2: 'Letter b',},

                'c':
                    { 0: 'Letter c',
                      1: 'Letter c',
                      2: 'Letter c',}

             }

My program, version 1; 我的程序,版本1; the expected results is the output. 预期结果就是输出。

# my_program.py
def fill_dict(a_dict, a_key):

    if not a_dict.has_key(a_key):
        a_dict[a_key] = {}

    for i in xrange(3):
        a_dict[a_key][i] = 'Letter {}'.format(a_key)

def main():
    main_dict = {}

    a_list = ['a', 'b', 'c']

    for item in a_list:
        fill_dict(main_dict, item)

if __name__ == '__main__':
    main()

Refactored program using defaultdicts ; 使用defaultdicts重构程序; result is main_dict = {} . 结果是main_dict = {}

# defaultdict_test.py
import collections

def fill_dict(a_dict, a_key):

    a_dict = collections.defaultdict(dict)

    for i in xrange(3):
        a_dict[a_key][i] = 'Letter {}'.format(a_key)

def main():
    main_dict = {}

    a_list = ['a', 'b', 'c']

    for item in a_list:
        fill_dict(main_dict, item)

if __name__ == '__main__':
    main()

Any pointers on what I'm doing wrong? 关于我在做什么的任何指示? Thanks. 谢谢。

You are passing main_dict into fill_dict , then assigning a new defaultdict to the local variable a_dict . main_dict fill_dict传递给fill_dict ,然后将新的defaultdict分配给局部变量a_dict You never pass that value back out. 您永远不会将这个价值传递出去。

In your program that works, you don't reassign the local, so when you call methods on a_dict, you are modifying the value passed in, which is the main_dict value from main. 在有效的程序中,您无需重新分配本地,因此,当您在a_dict上调用方法时,您正在修改传入的值,该值是main中的main_dict值。

This distinction, between reassigning, and mutating with methods, is subtle but important. 重新分配和方法变异之间的区别是微妙而重要的。 This article has more on names, values, and their interactions: Facts and myths about Python names and values . 本文提供了有关名称,值及其相互作用的更多信息: 有关Python名称和值的事实和神话

Pointers: 指标:

  1. Use in vs has_key in your first version. 在您的第一个版本中使用vs has_key The method has_key has been depricated and removed in Python 3 方法has_key已在Python 3中被描述并删除
  2. Remove a_dict = collections.defaultdict(dict) from fill_dict 除去a_dict = collections.defaultdict(dict)fill_dict
  3. Change main_dict = {} to main_dict = collections.defaultdict(dict) in main 变化main_dict = {}main_dict = collections.defaultdict(dict)main

Done! 做完了!

import collections

def fill_dict(a_dict, a_key):
    for i in xrange(3):
        a_dict[a_key][i] = 'Letter {}'.format(a_key)        

def main():
    main_dict = collections.defaultdict(dict)

    a_list = ['a', 'b', 'c']

    for item in a_list:
        fill_dict(main_dict, item)

Final pointer: Get to know list, set and dict comprehensions. 最后的指针:了解列表,设置和命令理解。 You can do this data structure in a single line: 您可以在一行中完成以下数据结构:

>>> {c:{i: 'Letter {}'.format(c) for i in range(3)} for c in 'abc'}
{'a': {0: 'Letter a', 1: 'Letter a', 2: 'Letter a'}, 'c': {0: 'Letter c', 1: 'Letter c', 2: 'Letter c'}, 'b': {0: 'Letter b', 1: 'Letter b', 2: 'Letter b'}}

If you look at it -- it is almost a version of what you have as your desired result if you format it that way: 如果您看一下-如果以这种方式格式化,它几乎是您想要的结果的一个版本:

dict_you_want={
                   c:
                       {  i: 'Letter {}'.format(c) 
                            for i in range(3)  }   # , 

                      for c in 'abc'
              }

which will execute just as I have it there... 它会像我在那里一样执行...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM