2010-02-09 3 views
3

나는 문제가 다음과 같은 기능을 잘못 무슨 일이 일어나고 있는지 이해의 비트에 봉착 :파이썬 바르() 전역 이름 오류

>>> ness() 
4 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 5, in ness 
NameError: global name 'yum' is not defined 
: 나는이 결과를 얻을 실행하면 그래서

def ness(): 
pie='yum' 
vars()[pie]=4 
print vars()[pie] 
print yum 

을 내가 함수로 작성하고 단지 명령 줄에서 한 번에 하나 개의 라인을 입력하지

경우 지금처럼 잘 작동 :

>>> pie='yum' 
>>> vars()[pie]=4 
>>> print vars()[pie] 
4 
>>> print yum 
4 
>>> 

편집 : yum을 값으로 설정하고 그 값을 출력하는 대신에, 좀 더 복잡하게 만들고 싶다고 가정하고, 몇 가지 함수를 정의하고 입력에 따라 그 중 하나를 호출하려고합니다 :

def ness(choo): 
    dic={} 
    dessert=() 
    dnum=[10,100] 
    desserts='pie' 
    dic[dessert]=str(desserts[bisect(dnum,choo)]) 
    vars()[dic[dessert]]() 
def p(): 
    print 'ummmm ummm' 
def i(): 
    print 'hooo aaaaa' 
def e(): 
    print 'woooo' 

그래서 내가 전화 할 때 나는 키 오류 얻을 다움 :

>>> ness(3) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 7, in ness 
KeyError: 'p' 

지금 내가 약간의 elif 문에이 같은 일을 할 수있어,하지만 난 양분이 너무 일하는 것이 궁금하고 사용하는 경우있어 내가 elifs를 사용하는 것보다 더 효율적일 것입니다 (말하자면 나는 choo의 1000 가지 값을 검사 할 필요가 있습니다).

도움을 주셔서 감사합니다.

답변

2

이 대신 새로운 딕셔너리를 사용하는 것이 더 안전하다는 것을 일을

>>> def ness(): 
... dic={} 
... pie='yum' 
... dic[pie]=4 
... print dic[pie] 
... print dic['yum'] 
... 
>>> ness() 
4 
4 
>>> 
+0

exec를 사용하면 위에서 쓴 더 복잡한 예를 볼 수 있습니다 (우리에게 시도하는 것과 같은 주요 오류는 없음). vars와 함께 dict. 정확히 정확히 dict를 exec보다 안전하게 사용합니까? "반환 된 사전을 수정하면 안됩니다 : 대응하는 기호 테이블의 효과가 정의되지 않았습니다" Doe 이렇게하면 exec를 사용하여이 방법을 사용하면 예기치 않은 문제가 발생할 수 있습니다. – Jamie

+0

exec는 예를 들어'exec "os.system ('reboot_your_pc')"과 같은 파이썬 코드를 실행할 수 있으므로 사용하지 않는 것이 가장 좋습니다. – YOU

+0

또한 exec는 혼란스럽게 stacktrace를 줄 수 있으며 명시 적 사전보다 훨씬 느립니다 (처음부터 매번 구문 분석되어야 함). – viraptor

1

이 바르에 의해 반환 된 DICT()

vars([object])¶

Without an argument, act like locals().

With a module, class or class instance object as argument (or anything else that has a dict attribute), return that attribute.

Note

The returned dictionary should not be modified: the effects on the corresponding symbol table are undefined.

두 번째 예는 특별한 경우를 수정 not safe을합니다. vars() 글로벌 네임 스페이스에 globals()에 해당하고, 사용자가 예상하는대로 globals()에 의해 반환 된 딕셔너리는 동작 (그러나 눈살을 찌푸리게한다) 함수 내에서

>>> id(vars()),id(globals()) 
(3085426868L, 3085426868L) 
4

vars() 그냥 locals()처럼, 당신에게 로컬 네임 스페이스를 제공합니다 - 참조 the docs. 함수 외부 (예 : 프롬프트에서) locals() (물론 vars())은 globals()처럼 모듈의 전역 네임 스페이스를 제공합니다. the docs이 말하듯이, locals() (또는 함수 내에서 vars())을 통해 함수의 지역 변수에 할당하려는 것은 Python에서 지원되지 않습니다. 변수에 글로벌 변수 변수를 지정하려면 프롬프트에있을 때 (또는 함수 외부에서)처럼 vars() 대신 globals()을 사용하십시오 (가장 명확한 접근 방법이 아닐 수도 있습니다 - 전역 변수는 당연히 싫은 눈살을 찌릅니다 -하지만 작동합니다).

0

vars()locals()과 같습니다. 함수의 경우 해당 범위의 로컬 변수이고 범위가 대화 형 인터프리터 인 경우 vars() is globals()입니다. locals()은 읽기 전용입니다. 그것을 변경하려고 할 때의 효과는 정의되지 않습니다 (실제로는 작동하지 않습니다). globals()이 수정 될 수도 있지만 여전히은 반환하는 dict에 직접 입력해서는 안됩니다.

0

[편집 : 나는 'exec'예제가 작동하기 때문에 틀린 것 같습니다.]

모두가 지적했듯이 vars()를 수정하는 것은 좋지 않습니다. 파이썬이 어떤 의미에서는 "yum"이 지역임을 "인식하지 못한다"는 것을 깨닫음으로써 오류를 이해할 수 있습니다. "print yum"은 여전히 ​​전역 참조로 해결됩니다. 이것은 어떤 코드가 실행되기 전에 발생합니다.

그것은 당신이에서 UnboundLocalError를 얻을 같은 이유 : 간부와

>>> def ness(): 
... pie='yum' 
... exec pie+"=4" 
... print vars()[pie] 
... print yum 
... 
>>> 
>>> ness() 
4 
4 

그것을 할 수있는 방법

>>> y = 100 
>>> def foo(x): 
... if x == 1: 
...  y = 10 
... print y 
... 
>>> foo(1) 
10 
>>> foo(2) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 4, in foo 
UnboundLocalError: local variable 'y' referenced before assignment