我有一些类似的代码:
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)}
因此,一般模式不是将元组的第一部分作为键,其余作为值。是否存在导致此行为的一些基本基础,或者只是,如果它确实会很方便....
答案 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转换显然是双向的。有三倍,它不可能(参见上面的例子)。