简体   繁体   English

为什么python dict这样表现呢?

[英]Why does python dict behave this way?

I have some code written like so: 我有一些这样写的代码:

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))

This code works like I want it to, but I'm curious as to why it works this way. 这段代码的工作方式与我想要的一样,但是我很好奇为什么会这样工作。 It is admittedly very convenient that it does work this way, but it seems like maybe I'm missing some underlying philosophy as to why that is. 以这种方式工作确实是很方便的,但是似乎我似乎缺少关于为什么这样做的一些基本哲学。

If I try something like: 如果我尝试类似的方法:

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

it doesn't create a dict that looks like 它不会创建看起来像

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

So the general pattern is not to take the first part of the tuple as the key and the rest as the value. 因此,通常的模式是不要以元组的第一部分作为键,其余部分作为值。 Is there some fundamental underpinning that causes this behavior, or it is just, well, it would be convenient if it did.... 是否有一些导致这种现象的根本原因,或者只是,如果这样做确实会很方便。

The constructor of dict accepts (among other things) a sequence of (key, value) tuples. dict的构造函数(除其他外)接受(key, value)元组序列。 Your second examples passes a list of tuples of length 3 instead of 2, and hence fails. 您的第二个示例传递了一个长度为3而不是2的元组列表,因此失败了。

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

however will create the dictionary 但是会创建字典

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

I think it's somewhat obvious. 我认为这很明显。 In your example, (1,2,3) is a single object. 在您的示例中, (1,2,3)是单个对象。 So the idea behind a dictionary is to map a key to a value (ie object). 因此,字典背后的想法是将key映射到value (即对象)。

So consider the output: 因此,请考虑以下输出:

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

But you can also do something like this: 但是您也可以执行以下操作:

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

Where the key is actually an object too! key实际上也是对象! In this case a tuple also. 在这种情况下,元组也是如此。

So in your example: 因此,在您的示例中:

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

how do you know which part of each tuple is the key and which is the value? 您如何知道每个元组的哪个部分是键,哪个是值?

If you find this annoying, it's a simple fix to write your own constructor: 如果您觉得这很烦,那么编写您自己的构造函数很简单:

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

Also, to Rafe's comment, you should define the dictionary right away: 另外,对于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)

If you ever want to iterate over the states, all you have to do is: 如果您想遍历各州,那么您要做的就是:

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

The construction of the dictionary in your change_state function is unnecessarily costly. change_state函数中构造字典的过程不必要地昂贵。

When you define the Django field, just do: 定义Django字段时,只需执行以下操作:

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

The general pattern is just this: you can create a dict from a list (in general: iterable) of pairs , treated as (key, value). 一般的模式是只这样的:你可以从一个列表的字典(一般:迭代器) ,视为(键,值)。 Anything longer would be arbitrary: why (1,2,3)->{1:(2,3)} and not (1,2,3)-> {(1,2):3}? 更长的东西将是任意的:为什么(1,2,3)-> {1:(2,3)}而不是(1,2,3)-> {(1,2):3}?

Moreover, the pairs<->dict conversion is obviously two-way. 此外,pairs-dict转换显然是双向的。 With triples it couldn't be (see the above example). 使用三元组则不可能(请参见上面的示例)。

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

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