为什么python dict会以这种方式运行?

时间:2011-03-27 18:09:09

标签: python

我有一些类似的代码:

class Invite(models.Model):
    STATE_UNKNOWN = 0
    STATE_WILL_PLAY = 1
    STATE_WONT_PLAY = 2
    STATE_READY = 3
    STATE_CHOICES = ((STATE_UNKNOWN, _("Unknown")),
                     (STATE_WILL_PLAY, _("Yes, I'll play")), 
                     (STATE_WONT_PLAY, _("Sorry, can't play")),
                     (STATE_READY, _("I'm ready to play now")))
    ...


    def change_state(self, state):
        assert(state in dict(Invite.STATE_CHOICES))

这段代码就像我想要的那样,但我很好奇它为什么会这样工作。它确实以这种方式工作是非常方便的,但似乎我可能缺少一些潜在的哲学,为什么会这样。

如果我尝试这样的话:

dict((1,2,3), (2,2,3), (3,2,3))
ValueError: dictionary update sequence element #0 has length 3; 2 is required

它不会创建看起来像

的字典
{1: (2,3), 2: (2,3), 3: (2,3)}

因此,一般模式不是将元组的第一部分作为键,其余作为值。是否存在导致此行为的一些基本基础,或者只是,如果它确实会很方便....

3 个答案:

答案 0 :(得分:3)

dict的构造函数接受(除其他外)一系列(key, value)元组。你的第二个例子传递了一个长度为3而不是2的元组列表,因此失败了。

dict([(1, (2, 3)), (2, (2, 3)), (3, (2, 3))])

然而会创建字典

{1: (2, 3), 2: (2, 3), 3: (2, 3)}

答案 1 :(得分:3)

我认为这有点显而易见。在您的示例中,(1,2,3)是单个对象。因此,字典背后的想法是将key映射到value(即对象)。

所以考虑输出:

>>> dict(((1,(2,3)), (2,(2,3)))).items()
[(1, (2, 3)), (2, (2, 3))]

但你也可以这样做:

>>> dict((((1,2),3), ((2,2),3)))
[((1, 2), 3), ((2, 2), 3)]

key实际上也是一个对象!在这种情况下,元组也是。

所以在你的例子中:

dict((1,2,3), (2,2,3), (3,2,3))

你怎么知道每个元组的哪个部分是关键,哪个是值?

如果您觉得这很烦人,那么编写自己的构造函数是一个简单的解决方法:

def special_dict(*args):
    return dict((arg[0], arg[1:]) for arg in args)

另外,对于Rafe的评论,你应该立即定义字典:

class Invite(models.Model):
    STATE_UNKNOWN = 0
    STATE_WILL_PLAY = 1
    STATE_WONT_PLAY = 2
    STATE_READY = 3
    STATE_CHOICES = dict(((STATE_UNKNOWN, _("Unknown")),
                     (STATE_WILL_PLAY, _("Yes, I'll play")), 
                     (STATE_WONT_PLAY, _("Sorry, can't play")),
                     (STATE_READY, _("I'm ready to play now"))))
    ...


    def change_state(self, state):
        assert(state in Invite.STATE_CHOICES)

如果你想迭代各州,你所要做的就是:

for state, description = Invite.STATE_CHOICES.iteritems():
    print "{0} == {1}".format(state, description)

change_state函数中构建字典会造成不必要的代价。

定义Django字段时,只需执行:

models.IntegerField(sorted(choices=Invite.STATE_CHOICES.iteritems()))

答案 2 :(得分:1)

一般模式就是这样:您可以从的列表(通常为:iterable)创建一个dict,视为(key,value)。任何更长的时间都是任意的:为什么(1,2,3) - > {1:(2,3)}而不是(1,2,3) - > {(1,2):3}?

此外,对< - > dict转换显然是双向的。有三倍,它不可能(参见上面的例子)。