2012-10-02 2 views
52

파이썬에서 globals()가 작동하는 이유는 무엇입니까? 이미 전역 변수 인 사전 만 반환하므로 어디서든 사용할 수 있습니다 ... 나는 호기심에서 벗어나 파이썬을 배우려고합니다.파이썬에서 전역()을 사용하는 이유는 무엇입니까?

def F(): 
    global x 
    x = 1 

def G(): 
    print(globals()["x"]) #will return value of global 'x', which is 1 

def H(): 
    print(x) #will also return value of global 'x', which, also, is 1 

F() 
G() 
H() 

여기에 요점이 실제로 표시되지 않습니까? 내가 로컬 및 글로벌 변수가 있다면 나는 그것을 필요 만 시간은 그들

def F(): 
    global x 
    x = 1 

def G(): 
    x = 5 
    print(x) #5 
    print(globals()["x"]) #1 

F() 
G() 

의 모두에 대해 같은 이름이었다하지만 당신은 같은 이름을 가진 두 개의 변수를 가진, 그리고 사용할 필요의 문제로 실행해서는 안됩니다 그것들은 모두 같은 범위 안에 있습니다.

+2

"하지만 같은 이름의 변수가 두 개 있고 같은 범위 내에서 둘 다 사용해야하는 문제는 절대로 있어서는 안됩니다." 나는이 생각을 따를 수 없다. 이것이 서로 다른 네임 스페이스의 다른 이유입니다. 서로 다른 범위에서 같은 이름의 변수를 사용한다는 것입니다. 둘 중 하나를 사용하여 작업 할 때 중복 된 이름은 자연스러운 것이지만 접두어로 사용할 수 있으므로 문제는 아닙니다. – Michael

+0

글쎄, 나는 C++ 계열에서 왔기 때문에 파이썬 사람들에 대해서는 잘 모르겠다.하지만 내가 생각할 수있는 한, 고유 한 이름을 가지고 있지 않은 글로벌 변수는 없어야한다. 동일한 범위의 동일한 이름의 변수가 내게 어리석은 문장이지만, 지역의 이름과 동일한 이름의 전역 변수는 아닙니다. 그 때 나는 네임 스페이스를 로컬 네임 스페이스에 사용할 것입니다 ... 그러나 그렇게 말하면 모르겠습니다. –

+3

@Mahi :'globalals'은 아마도 약간의 오해를 불러 일으킬 것입니다. 'globals()'는 본질적으로 모듈의'locals()'입니다.가장 가까운 파이썬은 모든 프로그램에서 전역 적으로 전역 변수에 온다. ['__builtin__' 모듈] (http://docs.python.org/library/__builtin__.html); * 그 * 모듈에 추가하는 것은 모든 곳의 모든 네임 스페이스에서 사용할 수있게됩니다. –

답변

71

파이썬은 프로그래머에게 실행 환경을 검사하는 많은 도구를 제공합니다. globals()은 그 중 하나 일 뿐이며 디버깅 세션에서 전역 범위에 실제로 포함 된 개체를 확인하는 데 매우 유용 할 수 있습니다.

locals()을 사용하여 함수에 정의 된 변수를 확인하거나 dir을 사용하여 모듈의 내용이나 객체의 속성을 확인하는 것과 같은 이유가 있습니다.

C++ 배경에서 볼 때 이러한 것들은 불필요한 것으로 이해할 수 있습니다. 정적으로 링크 된 정적 유형 환경에서는 절대적으로 그렇습니다. 이 경우 컴파일 타임에 정확히 어떤 변수가 전역인지, 객체의 구성원이 무엇인지, 그리고 다른 컴파일 단위에서 어떤 이름을 내 보냈는 지 알 수 있습니다.

그러나 동적 언어에서는 이러한 사항이 수정되지 않습니다. 코드를 가져 오는 방법이나 런타임 중에 변경 될 수 있습니다. 이런 이유로 최소한 디버거에서 이러한 종류의 정보에 액세스하는 것은 매우 중요합니다.

+9

+1. 또한,'globals'에 의해 반환 된 사전은 수정 될 수 있습니다 (아마 전문가에게 맡겨진 최고의 능력). [Dive Into Python] (http://www.diveintopython.net/html_processing/locals_and_globals.html)에서 인용 한 내용은 다음과 같습니다. "'locals' 및'globals' 함수를 사용하면 임의 변수의 값을 동적으로 얻을 수 있습니다. 변수 이름을 문자열로 제공합니다. 이것은 함수 이름을 문자열로 제공하여 임의 함수를 동적으로 액세스 할 수있게 해주는 getattr 함수의 기능을 반영합니다. " –

+1

당신의 대답이 다른 것보다 나아 졌다고 말하는 것은 아니지만 제게는 그렇습니다. 고마워, 나는 진정하고 파이썬이 C++이 아니라는 것을 기억해야한다. :) 그리고 응답하는 다른 모든 사람들에게도 감사의 말을 전한다. –

+0

보통 지역()에서 요소를 변경하면 효과가 없습니다. 대부분의 파이썬 함수는 지역에 대한 사전을 가지고 있지 않으므로 locals()를 호출 할 때 지역 변수의 현재 값에 대한 사전을 구성합니다. 그 변명을 바꾸는 것은 노동 조합 지부에 반영하지 않는다. 함수가 "import * from xyz"(더 이상 허용되지 않음)와 같은 일을하는 경우가있었습니다 - 컴파일 타임에 이름이 알려지지 않은 지역 주민을 설정합니다. 그 기능은 실제 지역 주민들의 명령으로 컴파일되었습니다. 오래 전에 * 모든 * 기능에는 실제 지역의 사전이 있었으며, 그 필요성을 단계적으로 없앴으며, 현재 어떤 조건에서 당신이 사전을 가지고 있는지 알지 못합니다. – greggo

5

globals()eval()에 유용합니다. 범위의 변수를 나타내는 일부 코드를 평가하려는 경우 변수는 전역 또는 지역에 있습니다.


eval() 내장 함수는 주어진 파이썬 코드의 문자열을 해석합니다, 조금 확장합니다. eval(codeString, globals, locals), 그리고 당신과 같이 사용할 것이다 : 서명은

def foo(): 
    x = 2 
    y = eval("x + 1", globals(), locals()) 
    print("y=" + y) # should be 3 

이 작동, 인터프리터는 변수의 locals() DICT에서 x의 값을 가져옵니다 때문이다. 물론 eval에 변수의 사전을 제공 할 수 있습니다.

+1

Downvoter : 설명에 설명해주십시오. –

+0

나는 downvoting을 한 사람이 아니었지만 이해가되지 않았다. 이해하기 쉽게 예제 코드를 줄 수 있었습니까? –

+0

물론, 나는 나의 대답을 확장했다. –

7

당신은 eval, execfile__import__ 명령에 globals()locals()의 결과를 전달할 수 있습니다. 이렇게하면 해당 명령이 작동 할 수있는 제한된 환경이 만들어집니다.

따라서 이러한 기능은 현재 컨텍스트와 잠재적으로 다른 환경을 제공함으로써 이익을 얻는 다른 기능을 지원하기 위해 존재합니다. 예를 들어, globals()을 호출 한 다음 해당 함수 중 하나를 호출하기 전에 일부 변수를 제거하거나 추가 할 수 있습니다.

30

함수의 문자열 이름을 사용하여 함수를 호출해야하는 경우에도 유용합니다. 예 :

def foo(): 
    pass 

function_name_as_string = 'foo' 

globals()[function_name_as_string]() # foo(). 
+3

나는 본다. 그게 좋은 습관인가요? –

+0

함수에 def foo (a, b, c = false)와 같은 많은 매개 변수가 있으면 어떻게 될까요? 어떻게 그런 매개 변수를 전역 변수에 전달하겠습니까? – ksooklall

+0

@ksooklall'def foo (* args) : print ("hw", * args)'와 함께 평소와 같이 함수에 넘깁니다.'globals() [ 'foo']()'또는'globals() [ 'foo'] ('reason', 42)'등등. – Tino

0

'선언적 비단뱀'에서 유용 할 수 있습니다.예를 들어 아래의 FooDefBarDef은 일련의 데이터 구조를 정의하는 데 사용되는 클래스로, 일부 패키지가 입력 또는 구성으로 사용합니다. 이렇게하면 입력 내용에 많은 유연성을 부여 할 수 있으며 파서를 작성할 필요가 없습니다. 이 구성 파일이 Foo_other의 구성의 일부인 이름의 목록을 구축하기 위해 루프를 사용하는

# FooDef, BarDef are classes 

Foo_one = FooDef("This one", opt1 = False, valence = 3) 
Foo_two = FooDef("The other one", valence = 6, parent = Foo_one) 

namelist = [] 
for i in range(6): 
    namelist.append("nm%03d"%i) 

Foo_other = FooDef("a third one", string_list = namelist) 

Bar_thing = BarDef((Foo_one, Foo_two), method = 'depth-first') 

참고. 그래서,이 설정 언어는 매우 강력한 '선처리 프로세서'와 함께 사용 가능한 런타임 라이브러리를 제공합니다. 예를 들어 구성을 생성 할 때 복잡한 로그를 찾거나 zip 파일에서 항목을 추출하고 base64를 디코드하려는 경우 (이 방법은 물론 권장되지 않습니다. 당신이 원하는 경우, 이러한 패키지를 사용하는 경우 globals()가 유용합니다, 그래서

conf_globals = {} # make a namespace 
# Give the config file the classes it needs 
conf_globals['FooDef']= mypkgconfig.FooDef # both of these are based ... 
conf_globals['BarDef']= mypkgconfig.BarDef # ... on .DefBase 

fname = "user.conf" 
try: 
    exec open(fname) in conf_globals 
except Exception: 
    ...as needed... 
# now find all the definitions in there 
# (I'm assuming the names they are defined with are 
# significant to interpreting the data; so they 
# are stored under those keys here). 

defs = {} 
for nm,val in conf_globals.items(): 
    if isinstance(val,mypkgconfig.DefBase): 
     defs[nm] = val 

, 마지막 지점에 도착 : 신뢰할 수없는 소스 ...)

패키지는 다음과 같은 것을 사용하여 구성을 읽고 절차 적으로 일련의 정의를 작성하십시오 :

for idx in range(20): 
    varname = "Foo_%02d" % i 
    globals()[varname]= FooDef("one of several", id_code = i+1, scale_ratio = 2**i) 
,

Foo_00 = FooDef("one of several", id_code = 1, scale_ratio=1) 
Foo_01 = FooDef("one of several", id_code = 2, scale_ratio=2) 
Foo_02 = FooDef("one of several", id_code = 3, scale_ratio=4) 
... 17 more ... 

에게 파이썬 모듈에서 정의의 무리를 수집하여 그 입력을 획득하고 패키지의 일례를 작성 동등하면 PLY (파이썬 렉스-은 yacc) http://www.dabeaz.com/ply/하다 -이 경우에 객체는 대부분 함수 객체이지만 함수 객체의 메타 데이터 (이름, 문서 문자열 및 정의 순서)도 입력의 일부를 형성합니다. globals()을 사용하는 것은 좋은 사례가 아닙니다. 또한 '구성'에 의해 가져옵니다. 후자는 일반적인 파이썬 스크립트입니다.

필자가 작업 한 몇 개의 프로젝트에서 '선언적 python'을 사용했으며, 구성을 작성할 때 globals()을 사용할 기회가있었습니다. 당신은 이것이 구성 '언어'가 디자인 된 방식의 약점 때문이라고 확실히 말할 수 있습니다. 이 방법으로 globals()을 사용하더라도 매우 명확한 결과가 나오지 않습니다. 거의 동일한 진술을 12 개 이상 작성하는 것보다 유지하기가 더 쉬운 결과 일뿐입니다.

또한 자신의 이름에 따라, 구성 파일 내에서 변수의 의미를 부여하는 데 사용할 수 있습니다 :

# All variables above here starting with Foo_k_ are collected 
# in Bar_klist 
# 
foo_k = [ v for k,v in globals().items() if k.startswith('Foo_k_')] 
Bar_klist = BarDef(foo_k , method = "kset") 

이 방법은 테이블과 구조의 많은 영역을 정의하는 파이썬 모듈이 유용 할 수있다, 참조를 유지 관리 할 필요없이 항목을 데이터에 더 쉽게 추가 할 수 있습니다.

관련 문제