Python setdefault()方法在这个反转字典实现中是如何工作的?

Python setdefault()方法在这个反转字典实现中是如何工作的?,python,methods,setdefault,Python,Methods,Setdefault,有人能解释一下,在下面的例子中,字典“逆”的赋值是如何发生的吗 def invert_dict(d): inverse = {} for key in d: new_key = d[key] inverse.setdefault(new_key, []).append(key) return inverse letters_in_word = {"mine": 4, "yours": 5, "ours":

有人能解释一下,在下面的例子中,字典“逆”的赋值是如何发生的吗

def invert_dict(d):
  inverse = {}
  for key in d:
    new_key = d[key]
    inverse.setdefault(new_key, []).append(key)
  return inverse

letters_in_word = {"mine": 4, "yours": 5, "ours": 4, "sunday": 6, "friend": 6, "fun": 3, "happy": 5, "beautiful": 8}

print (invert_dict(letters_in_word))
当然,输出是正确的:

{8:['beauty'],3:['fun'],4:['mine','ours'],5:['happy','yours'],6:['sunday','friend']}

Python 3.x文档说明:

设置默认值(键[,默认值]):

如果键在字典中,则返回其值。如果不是,则插入值为default的键并返回default。默认值为“无”

让我用一个例子来说明我所做的和不理解的事情:

  • 假设新的_key=“快乐”
  • 新_键的值为5
  • setdefault()被调用,我们假设5已经从“yours”(据我所知,因为字典是无序的,所以这不一定是这样,但让我们假设),并将返回[“yours”](我猜这里会发生一些稍有不同的情况,因此实际上“reverse.setdefault(5,[])不是真的已返回[“您的”]仅此而已)
  • 调用append()并[“yours”]-->[“yours”,“happy”]-这就是我们剩下的内容
  • 我知道在4月底之前我错了,因为事实上我们的列表已经被分配到了键“5”。我不明白的是事情发生的时间点——看起来我们刚回来,真的应该分配:

    inverse[new_key] = inverse.setdefault(new_key, []).append(key)
    
    但是,如果像这样运行代码,则会出现错误-
    “NoneType”对象没有属性“append”

    任何解释都是值得赞赏的——我想我一定遗漏了关于这两种方法是如何相互作用的


    另外,这是我的第一个问题,如果问题的性质/结构不是“这里的事情是怎么做的”,我表示歉意。让我知道如何改进,我会尽我最大的努力

    打印语句是理解程序中发生的事情的一种非常有用且简单的方法:

    def invert_dict(d):
        inverse = {}
        for key in d:
            new_key = d[key]
            print('key:', key)
            print('new_key:', new_key)
            print('inverse before:', inverse)
            value = inverse.setdefault(new_key, [])
            print('inverse in the middle:', inverse)
            print('value before:', value)
            value.append(key)
            print('value after:', value)
            print('inverse after:', inverse)
        return inverse
    
    letters_in_word = {"mine": 4, "yours": 5, "ours": 4, "sunday": 6, "friend": 6, "fun": 3, "happy": 5, "beautiful": 8}
    
    print(invert_dict(letters_in_word))
    
    输出:

    key: beautiful
    new_key: 8
    inverse before: {}
    inverse in the middle: {8: []}
    value before: []
    value after: ['beautiful']
    inverse after: {8: ['beautiful']}
    key: yours
    new_key: 5
    inverse before: {8: ['beautiful']}
    inverse in the middle: {8: ['beautiful'], 5: []}
    value before: []
    value after: ['yours']
    inverse after: {8: ['beautiful'], 5: ['yours']}
    key: ours
    new_key: 4
    inverse before: {8: ['beautiful'], 5: ['yours']}
    inverse in the middle: {8: ['beautiful'], 4: [], 5: ['yours']}
    value before: []
    value after: ['ours']
    inverse after: {8: ['beautiful'], 4: ['ours'], 5: ['yours']}
    key: sunday
    new_key: 6
    inverse before: {8: ['beautiful'], 4: ['ours'], 5: ['yours']}
    inverse in the middle: {8: ['beautiful'], 4: ['ours'], 5: ['yours'], 6: []}
    value before: []
    value after: ['sunday']
    inverse after: {8: ['beautiful'], 4: ['ours'], 5: ['yours'], 6: ['sunday']}
    key: happy
    new_key: 5
    inverse before: {8: ['beautiful'], 4: ['ours'], 5: ['yours'], 6: ['sunday']}
    inverse in the middle: {8: ['beautiful'], 4: ['ours'], 5: ['yours'], 6: ['sunday']}
    value before: ['yours']
    value after: ['yours', 'happy']
    inverse after: {8: ['beautiful'], 4: ['ours'], 5: ['yours', 'happy'], 6: ['sunday']}
    key: fun
    new_key: 3
    inverse before: {8: ['beautiful'], 4: ['ours'], 5: ['yours', 'happy'], 6: ['sunday']}
    inverse in the middle: {8: ['beautiful'], 3: [], 4: ['ours'], 5: ['yours', 'happy'], 6: ['sunday']}
    value before: []
    value after: ['fun']
    inverse after: {8: ['beautiful'], 3: ['fun'], 4: ['ours'], 5: ['yours', 'happy'], 6: ['sunday']}
    key: mine
    new_key: 4
    inverse before: {8: ['beautiful'], 3: ['fun'], 4: ['ours'], 5: ['yours', 'happy'], 6: ['sunday']}
    inverse in the middle: {8: ['beautiful'], 3: ['fun'], 4: ['ours'], 5: ['yours', 'happy'], 6: ['sunday']}
    value before: ['ours']
    value after: ['ours', 'mine']
    inverse after: {8: ['beautiful'], 3: ['fun'], 4: ['ours', 'mine'], 5: ['yours', 'happy'], 6: ['sunday']}
    key: friend
    new_key: 6
    inverse before: {8: ['beautiful'], 3: ['fun'], 4: ['ours', 'mine'], 5: ['yours', 'happy'], 6: ['sunday']}
    inverse in the middle: {8: ['beautiful'], 3: ['fun'], 4: ['ours', 'mine'], 5: ['yours', 'happy'], 6: ['sunday']}
    value before: ['sunday']
    value after: ['sunday', 'friend']
    inverse after: {8: ['beautiful'], 3: ['fun'], 4: ['ours', 'mine'], 5: ['yours', 'happy'], 6: ['sunday', 'friend']}
    {8: ['beautiful'], 3: ['fun'], 4: ['ours', 'mine'], 5: ['yours', 'happy'], 6: ['sunday', 'friend']}
    

    还有一个非常有用的调试器,比如PyCharm中的调试器。试试看。

    注意
    list.append
    总是返回
    None
    @MoinuddinQuadri我在发帖前读过,但在那里看不到我问题的答案。我会重新阅读,可能是我的问题的答案在那里,但我无法“看到”或理解相关的部分。我会再试一次@mgilson啊,好吧,这就解释了为什么我的反向[new_key]行永远无法解决这个问题。
    inverse.setdefault(new_key,[])。append(key)
    将使用
    new_key
    键向
    列表添加一个条目。您不必像
    .append()
    返回
    None
    值那样执行
    inverse[new_key]=…
    。听起来您误解了Python中变量、引用和可变对象的交互方式。我推荐阅读-我保证它是相关的。谢谢你-它有助于跟踪问题。对我来说真正没有意义的步骤是:{8:['beautifuly']}
    之后的
    倒数。我看不出调用
    value.append(key)
    如何改变变量
    value
    也在改变
    inverse
    。同样感谢您提供的调试器提示@cjjob,因为变量
    中的列表值是同一个对象,而不是单独的副本。对“一”的任何更改也会更改“另一”,因为它们是一个整体<代码>值为反向[新建\u键]
    返回
    True
    @cjjob
    value
    不是独立或孤立的列表,是对内存中某个位置的实际列表的引用,同样适用于
    反向中的列表。检查一下关于这个主题的讲座:@Copperfield[和Alex Hall]是的,谢谢你们两位的帮助!现在一切都有了意义——我没有意识到它们是同一个物体。。。