2016-09-09 2 views
0

나는 함수가 있고 전달 된 인수를 얻고 싶다. 나는 locals()을 통해이를 달성했지만, 나는 locals()이 아닌 값 쌍의 키를 그만 둘 :`x for locals() :`- RuntimeError : locals()가 크기를 변경하는 이유는 무엇입니까?

>>>def print_params(i,j,k): 
    for x in locals(): 
     print(x) 
>>>print_params('a','b','c') 
j 
i 
k  #<--I want to get back 'a','b','c'. 

내가 locals()에서 대신 키의 값을 좀하고 싶습니다. 일반 DICT와

는, 내가이 작업을 수행 할 수 있습니다 알고 : 나는 locals() 이것을 시도하는 경우,

>>> m = { 
... 'a' : 'b', 
... 'y' : 'z'} 
>>> m 
{'a': 'b', 'y': 'z'} 
>>> for x in m: 
...  print(x) 
... 
a  # <--Keys 
y 
>>> for x in m: 
...  print(m[x]) 
... 
b  # <--Values 
z 

그러나, 그것은 RuntimeError에 만들어집니다.

>>> def print_args(i,j,k): 
...  for x in locals(): 
...   print(locals()[x]) 
... 
>>> print_args('a','b','c') 
b       # <--Got one! 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 2, in y 
RuntimeError: dictionary changed size during iteration 

누군가 무슨 일이 일어 났는지 설명 할 수 있습니까? 오류가 발생하기 전에 인쇄해야하는 단일 값에서 루프가 locals()의 다음 요소로 반복하려고 시도 할 때 오류가 발생하는 것을 볼 수 있습니다. 그 다음, dict이 수정되면서, 그것의 자리를 잃는다. 하지만 왜 사전 크기가 변해야하는지 이해할 수 없습니다. 나는 각각의 패스에서 for 루프를 통과 할 때 변수 x이 파괴 된 다음 루프를 통해 다음 패스를 위해 다시 생성된다고 추측합니다. 그러나 이것은 이상한 것처럼 보입니다. 왜냐하면 x을 "활성"상태로 유지하고 각 반복마다 새로운 값으로 다시 할당하는 것이 더 효율적이라고 생각할 것이기 때문입니다.

는 궁극적으로, 난 그냥 local_args = locals()을 할 수있는 것 같아요,하지만 난 정확히 일어나고 것은 단순히 locals() 통해 반복에서 저를 방지 무엇으로 여전히 궁금하다. x이 파괴되고 재현되는 것이 맞는지 확실하지 않습니다. 나는 그것이 무엇인지 궁금해해야만합니다. 그렇지 않다면 나는 무엇이 일어나고 있는지 더 궁금합니다.

+2

'x'는 새로운 변수이므로 로컬 변수 사전에서 새 항목입니다. – zondo

+0

"하지만,'locals()'로 이것을 시도하면"아니오, 당신은 미묘하게 다른 것을 시도했습니다. –

+1

당신은'locals()'를 사용하지 않아도됩니다. 왜 당신의 함수는'def print_params (* i) :'그리고'for x in i : print (x)'또는'print (* i)'가 될 수 없습니까? 그것들을 전달할 때 인수의 원래 순서를 유지할 수도 있습니다. – TigerhawkT3

답변

1

Can someone explain what's happening? From the single value I got to print (before it errors out), I can see that the error arises when the loop attempts to iterate to the next element of locals(); then, as the dict has been modified, it loses its place. I can't make sense of why the dictionary size should change, though. I'm inferring that, on each pass through the for loop, the variable x is destroyed, then re-created for the next pass through the loop. However, this seems odd, since I would think it'd be more efficient to keep x "alive" and just re-assign it to the new value on each iteration.

변수 x 한 번만 생성되지만이 만들어지지 않습니다 locals()을 반복합니다. for 루프의 소스 ​​iterable은 루프 변수에 할당되기 전에 평가됩니다. 그러나 오류 메시지는 dict 자체 (또는 iterator)에 의해 발생합니다. 즉, iterate하려고 할 때 "주목"하고 마지막 반복 이후 변경된 경우입니다.그래서 무슨 일입니다 :

  1. locals()을 평가하고 당신에게
  2. for 루프가 DICT의 반복자를 생성하는 딕셔너리를 제공하고 첫 번째 요소를 얻을 수
  3. 새 로컬 x가 생성되고 먼저로 설정 다음 루프 반복의 요소
  4. for 루프는합니다 (DICT 반복자
  5. 기본 DICT 새로운 요소를 가지고 DICT 반복자 고지에서 다른 요소를 가져 오려고 시도3210) 마지막 반복 이후 오류를 발생시킵니다.

간단한 해결 방법은 루프 앞에 몇 가지 더미 값이있는 x 변수를 만드는 것입니다. 그런 다음 루프 동안 새로운 변수를 더 만들 당신이 이제까지 locals() 액세스하기 전에 이미 존재하지 않는, 존재가 될 것입니다 :

def print_args(i,j,k): 
    x = None 
    for x in locals(): 
     print(locals()[x]) 

>>> print_args('a', 'b', 'c') 
a 
x 
c 
b 

공지 사항을 물론, 당신은 또한이 반복 동안 x 자체를 얻을 것이다.

다른 사람들이 의견에서 언급했듯이, 왜 당신이이 일을 왜하는지 분명하지 않습니다. locals()은 다소 미끄러운 짐승이며 대개 성취하려는 실제적인 작업을 감안할 때 locals()을 사용하지 않고 더 좋은 방법이 있습니다.

+0

나는 다른 사람들이 말하는 것에 기초하여 지금 그것을 깨닫는다. 방금 함수의 주장을 되 찾으려했기 때문에'locals()'가 존재한다는 것을 알았습니다. 그것은 어딘가에 제안되었습니다. 가장 좋은 해결책은'function (* i)'을 사용하는 것인데, 나는 인수 만 받겠다는 점을 고려할 때 훨씬 더 좋아 보인다. –

0

for x in locals()으로 전화 할 때 locals()이 평가되면 첫 번째 항목은 x에 저장됩니다. x은 이전에 정의되지 않았으므로 첫 번째 루프 중에 locals 사전에 추가되고 두 ​​번째 루프는 변경 사항을 통지합니다.

당신이 언급 한대로이 workarounding의 한 가지 방법은 미리 locals 사전을 복사하는 것입니다

: 당신이 시작할 때까지

def print_args(i,j,k): 
    local_args = dict(locals()) 
    for x in local_args: 
     print(local_args[x]) 

print_args('a','b','c') 
관련 문제