2017-12-21 4 views
1

해당 함수에 대한 참조가 포함 된 함수와 사전이 있습니다.데이터 구조 내에서 함수 이름을 가져올 수없는 이유

def func1(): print('blah') 

dict1 = {'func1': func1} 

주어진 순서대로 파이썬 인터프리터에 붙여 넣으면 모두 정상적으로 작동합니다. 내가 파일에서 dict1을 가져 오는 경우

`>>> def func1(): print('blah') 
... 

>>> func1 
<function func1 at 0x7f8939d77730> 

>>> func1() 
blah 

>>> dict1 = {'func1': func1} 
>>> dict1['func1']() 
blah 

` 

는하지만, 인터프리터는 func1가가 정의되어 있어도, 정의되지 않은 말한다.

그래서 파일 'dictfile.py'한 줄의 텍스트 포함과 :

>>> def func1(): print('blah') 
... 
>>> func1() 
blah 

>>> from dictfile import * 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/../dictfile.py", line 1, in <module> 
    dict1 = {'func1': func1} 
NameError: name 'func1' is not defined 
>>> 

여기 무슨 일이야 : 인터프리터에 그런 다음이

dict1 = {'func1': func1} 

를?

+1

런타임에 func1 참조가 존재하므로 파일에서 저장하거나로드 할 수 없습니다. –

+0

은'getattr (module, func1)'과 같이 무언가를 사용하여 dict에 값을 할당합니다. –

+0

Raghava의 코멘트는 유용하고 유익하며 대답과 같게 들립니다. 정교하게 주시겠습니까? – markling

답변

3

func1dictfile.py 컨텍스트의 범위에 정의되어 있지 않습니다.

'func1'의 전역 범위는 자신을 정의하는 것으로 제한됩니다. 이것은 자체 내장 모듈로 작동 할 수 있도록 설계되었습니다. 즉, 모듈이 작동해야하므로 작동 할 수 있으므로 다른 모듈에서 가져 와서 실행할 수 있습니다. 이는 서로 다른 모듈이 전역 정의에서 다른 것들에 대해 동일한 이름을 사용할 때 충돌을 피하기 위해 수행됩니다. 파이썬 docs에서

:

따라서, 사용자의 글로벌 변수와 우발적 인 충돌에 대한 걱정없이 모듈 에서 전역 변수를 사용할 수있는 모듈의 저자.

파일을 import 문으로로드하면 모듈이됩니다. 그러면 해당 모듈이 가져 오기 범위에서 가져 오기를 기대할 수 없습니다. 자신의 범위는 분명히 남아 있습니다. 무결성이 보호됩니다. 자체 정의하지 않으면 사용하는 정의를 가져와야합니다.

함수를 참조하는 사전을로드하려면 해당 함수가 위치한 함수 (파일)에 함수를 정의해야합니다.

파일이 현재 사용자의 인터프리터 상태 (파일에 상태를 가져 오지 못하고 가능한 경우 확실하지 않음)에 대해 알지 못하기 때문에 함수에 대한 참조를 찾을 수 없습니다. 파이썬 docs 따르면

,

각 모듈은 모듈에 정의 된 모든 기능에 의해 글로벌 심볼 테이블로서 사용되는 그 자신의 개인 기호 테이블을 갖는다. 따라서 모듈의 작성자 은 사용자의 전역 변수와의 충돌에 대해 걱정하지 않고 모듈의 전역 변수를 사용할 수 있습니다. 다른 한편으로, 무엇을하고 있는지 알고있는 경우 모듈의 전역 변수를 함수, modname.itemname을 참조하는 데 사용 된 표기법과 함께 사용할 수 있습니다.

모듈의 (파일의) 범위에서 기능에 액세스하려면 대화식 인터프리터의 "모듈"을 가져와야합니다. 이는 가능하지 않다고 생각합니다.

+0

감사합니다. 그리고 그렇습니다, 그것이 사실 인 것처럼 보입니다. 그런데 왜 이렇게됩니까? 그것은 직관력이없는 것처럼 보입니다. 내 범위에 정의 된 함수가 있습니다. 그런 다음 해당 범위에 해당 함수에 대한 참조가 들어있는 선언을 호출합니다. 그 선언을 내 범위에 가져오고 있기 때문에, 내가 언급 한 대상을 포함하는 범위에서 선언을하지 않습니까? delcaration은 분명히 바보 파일에 만들어지지 않습니다. 그것은 파일을 가져올 때 만들어지며 파일을 가져올 때 필요한 기능이 내 범위에 정의됩니다. – markling

+0

@markling 업데이트 된 답변보기; 그것을 설명하는 데 도움이되는 Python 문서에서 찾은 몇 가지 세부 정보를 추가했습니다. –

+1

감사합니다, @ Pedro-von-Hertwig. 나는 당신의 대답을 편집하여 그 부분을 정교하게 다듬 었습니다. 나는이 문제를 이해하는데 가장 유익하다고 느꼈습니다. – markling

3

각 모듈은 네임 스페이스를 정의하므로 모듈의 "전역"변수는 실제로 해당 모듈에 적용됩니다. 다른 모듈이 액세스 할 수 있지만 이름을 정의한 모듈을 통해 액세스해야합니다.

대화식 세션에서 실행하는 경우 생성 한 개체가 __main__이라는 특수 모듈에 추가됩니다. 다른 모듈 에서 가져올 수 있지만 원한다면 가져 오지 않는 것이 좋습니다. 단지 학습 목적을 위해 예를 들어

: 실제 프로그램에서

$ cat dictfile.py 
from __main__ import func1 
dict1 = {'func1': func1} 

$ python 
Python 2.7.10 (default, Jul 30 2016, 19:40:32) 
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.34)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> def func1(): print('blah') 
... 
>>> from dictfile import dict1 
>>> dict1 
{'func1': <function func1 at 0x102735c08>} 
>>> dict1['func1']() 
blah 

,이 같은 순환 종속성을 피해야한다. 그러나 한 모듈에서 함수를 가져 와서 다른 모듈의 데이터 구조로 어셈블 한 다음 세 번째 모듈의 데이터 구조를 사용하는 것이 여전히 유용 할 수 있습니다.

프로그램 부분 간의 종속성에 대한 경험적 규칙 : 구현은 추상화에만 의존해야하며 추상화는 다른 추상화에만 의존해야합니다.

+0

예,이 cicular 종속성은 정확히 내가 만든 것입니다. 그리고 즉시 다른 문제로 동일한 목적을 달성하기 위해 수행해야 할 작업에 대한 향후 고려 사항을 위해 따로 질문을 던져 버릴 것입니다. 고맙습니다. – markling

관련 문제