2011-03-27 3 views
0

다음과 같이 작성된 코드가 있습니다.왜 파이썬 사전은 이런 식으로 행동합니까?

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 

xxx43

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

와 같은 dict을 만들지 않습니다. 따라서 일반적인 패턴은 튜플의 첫 번째 부분을 키로, 나머지는 값으로 사용합니다. 이 동작을 일으키는 몇 가지 근본적인 토대가 있습니까, 아니면 단지 잘되었을 때 편리 할 것입니다 ....

+0

이 보면 정말 어렵다. 왜 튜플 (tuple)의 튜플 (tuple)로 구성하지 않고 처음에 사전을 정의하지 않았습니까? –

+0

장고 선택 필드는 2 튜플의 순서 여야합니다. 그것에 대해 할 수있는 일은별로 없습니다. – boatcoder

답변

3

나는 그것이 다소 명백하다고 생각합니다. 귀하의 예에서 (1,2,3)은 단일 개체입니다. 따라서 사전의 배경은 keyvalue (즉, 객체)에 매핑하는 것입니다.

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

또한, 레이프의 의견에, 당신은 바로 사전을 정의해야합니다 :

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 함수 사전에 불필요하게 많은 비용이 듭니다.

당신이 장고 필드를 정의

, 그냥 수행

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

일단 내가 어떻게 작동하는지 알았 더라면 나에게도 명백한 것처럼 보였습니다. 나는 언어의 구현 자에게 이것이 그렇게되어야한다는 것을 분명하게 생각한 것이다. 때때로 사물의 이유를 배우는 것은 다른 사물에 대한 이해를 증진시킵니다. – boatcoder

+0

귀도는 똑똑한 사람입니다. :) – milkypostman

3

dict의 생성자는 (특히) (key, value) 튜플의 시퀀스를 허용합니다. 두 번째 예제는 2 대신 길이가 3 인 튜플 목록을 전달하므로 실패합니다.

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

그러나 사전

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

그는 자신이 원하는 것을 수행하는 방법을 묻지 않고 있으며, 'dict'생성자가 왜 그렇게 설계되었는지 묻습니다. – milkypostman

+0

@milky, 그 대답은 질문에 주어집니다. 그것은 사전을 구성하는 매우 편리한 방법이기 때문에 그런 식으로 작동합니다. –

1

을 만듭니다 일반적인 패턴 그냥이 : 당신이 목록에서 딕셔너리를 생성 할 수 있습니다 (일반적으로 : 반복 가능) 의 (주요 취급, 값). 무엇이든 더 이상 임의적 일 것입니다 : 왜 (1,2,3) -> {1 : (2,3)}이 아닌 (1,2,3) -> {(1,2) : 3}입니까?

또한, < 쌍의 변환은 분명히 양방향입니다. 트리플을 사용하면 위의 예를 볼 수 없습니다.

관련 문제