2016-09-22 8 views
10

다음이 실행 :로컬을 지정할 때 파이썬 3 exec()가 실패하는 이유는 무엇입니까? 파이썬 3에서 오류없이

code = """ 
import math 

def func(x): 
    return math.sin(x) 

func(10) 
""" 
_globals = {} 
exec(code, _globals) 

하지만 나뿐만 아니라 지역 변수 DICT를 캡처하려고하면, 그것은 NameError와 함께 실패

>>> _globals, _locals = {}, {} 
>>> exec(code, _globals, _locals) 
--------------------------------------------------------------------------- 
NameError         Traceback (most recent call last) 
<ipython-input-9-aeda81bf0af1> in <module>() 
----> 1 exec(code, {}, {}) 

<string> in <module>() 

<string> in func(x) 

NameError: name 'math' is not defined 

왜이 일어나고, 전역 변수와 지역 변수를 모두 캡처하면서 어떻게이 코드를 실행할 수 있습니까? exec() documentation에서

답변

10

:

은 모듈 수준에서 그 기억, 전역과 지역 주민이 같은 사전입니다. exec이 두 개의 개별 객체 인 ,지역인 인 경우 코드는 클래스 정의에 포함 된 것처럼 실행됩니다.

두 개의 별도 사전을 전달했지만 모듈 범위 전역을 사용할 수 있어야하는 코드를 실행하려고했습니다. import math로컬 범위 속성을 생성하며 클래스 범위 이름이 함수 종료로 간주되지 않으므로 사용자가 만든 함수에 액세스 할 수 없습니다.

파이썬 실행 모델 참조 Naming and binding를 참조하십시오 exec()eval()

클래스 정의 블록 및 인수가 이름 확인의 맥락에서 특별하다. 클래스 정의는 이름을 사용하고 정의 할 수있는 실행 가능 명령문입니다. 이러한 참조는 글로벌 네임 스페이스에서 언 바운드 로컬 변수를 조회하는 경우를 제외하고 이름 확인을위한 일반적인 규칙을 따릅니다. 클래스 정의의 네임 스페이스가 클래스의 속성 사전이됩니다. 클래스 블록에 정의 된 이름의 범위는 클래스 블록으로 제한됩니다. 이 메소드의 코드 블록으로 확장되지 않습니다

당신은 클래스 정의의 코드를 실행하려고하여 오류를 재현 할 수 있습니다 [.] :

>>> class Demo: 
...  import math 
...  def func(x): 
...   return math.sin(x) 
...  func(10) 
... 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 5, in Demo 
    File "<stdin>", line 4, in func 
NameError: name 'math' is not defined 

그냥 사전에 전달합니다.

+0

"클래스 정의에 포함 된 것처럼"문구의 의미를 풀 수 있습니까? 그리고/또는 "클래스 범위 이름이 함수 클로저로 간주되지 않는"방법에 대한 구체적인 예를 들어주십시오. – jez

+0

@jez : [* 이름 확인 *] (https://docs.python.org/3/reference/executionmodel.html#resolution-of-names) 참조 : * 클래스 정의 블록과'exec()'에 대한 인수. 과'eval()'은 이름 해석의 문맥에서 특별하다. 클래스 정의는 이름을 사용하고 정의 할 수있는 실행 가능 명령문입니다. 이러한 참조는 전역 네임 스페이스에서 언 바운드 로컬 변수를 찾지 않는 예외적 인 이름 확인을위한 일반적인 규칙을 따릅니다. * –

+0

여기에 표시된 동작은 내부적으로 메서드를 정의 할 때 나타나는 동작과 완전히 동일하다는 것을 명시 적으로 설명하는 것이 좋습니다. 클래스 정의 (현재의 대답은 그것을 말하고 있지만 "method"라는 단어는 사용하지 않습니다)를 강조하고 클래스 정의 내부의 질문에서 코드를 반복하여 강조합니다. 또한, exec ("def _dummy() : \ n {} \ n_dummy()"형식으로 실행되도록 깔끔한 트릭을 작성한다. format ("\ n".join (code.strip() .splitlines())), {}, {})' – ncoghlan