globals (), locals () 및 vars ()의 차이점은 무엇입니까?


146

차이점은 무엇이며 globals(), locals()그리고는 vars()? 그들은 무엇을 반환합니까? 결과 업데이트가 유용합니까?


파이썬 3에서 이것들 중 하나를 업데이트하고 스크립트가 실제로 작동하도록 할 수 있습니까?
Charlie Parker

답변:


172

이들 각각은 사전을 반환합니다.

  • globals() 항상 모듈 네임 스페이스 의 사전을 반환합니다
  • locals() 항상 현재 네임 스페이스 사전을 반환 합니다
  • vars()반환 중 하나 (인수없이 호출하는 경우) 현재 이름 공간 또는 사전 인수의 사전.

locals그리고 vars좀 더 설명을 사용할 수 있습니다. locals()함수 내에서 호출 된 경우 현재 시점에서 현재 로컬 변수 네임 스페이스 값 (닫기 변수 포함)으로 dict를 업데이트하여 반환합니다. locals()동일한 스택 프레임에서 여러 번의 호출은 매번 동일한 dict를 반환 f_locals합니다. 속성 은 스택 프레임 객체에 연결됩니다 . dict의 내용은 각 locals()호출 및 각 f_locals속성 액세스에서 업데이트 되지만 해당 호출 또는 속성 액세스 에서만 업데이트됩니다 . 변수가 할당 될 때 자동으로 업데이트되지 않으며 dict에 항목을 할당해도 해당 로컬 변수가 할당되지 않습니다.

import inspect

def f():
    x = 1
    l = locals()
    print(l)
    locals()
    print(l)
    x = 2
    print(x, l['x'])
    l['x'] = 3
    print(x, l['x'])
    inspect.currentframe().f_locals
    print(x, l['x'])

f()

우리에게 주어지다:

{'x': 1}
{'x': 1, 'l': {...}}
2 1
2 3
2 2

첫 번째 항목 은 통화 후 할당이 수행되므로 항목 print(l)만 표시합니다 . 두 번째 는 다시 호출 한 후 반환 값을 저장하지 않았지만 항목을 표시 합니다. 세 번째와 네 번째 변수는 변수를 할당해도 업데이트되지 않으며 그 반대도 마찬가지이지만 액세스 한 후에는 로컬 변수가 다시 복사 됩니다.'x'llocals()print(l)locals()lprintlf_localslocals()

두 가지 메모 :

  1. 이 동작은 CPython에 따라 다릅니다. 다른 Python에서는 업데이트를 통해 로컬 네임 스페이스로 자동으로 업데이트 할 수 있습니다.
  2. CPython 2.x에서는 exec "pass"함수에 라인을 추가 하여이 작업을 수행 할 수 있습니다. 이를 통해 함수를 locals()지역 변수의 표준 표현으로 dict 를 사용하는 이전의 느린 실행 모드로 전환 합니다.

경우 locals()라고 외부 함수는 현재 네임 스페이스 실제 사전을 반환합니다. 네임 스페이스에 추가 변경 되어 사전에 반영하고, 사전에 변경 하는 네임 스페이스에 반영 :

class Test(object):
    a = 'one'
    b = 'two'
    huh = locals()
    c = 'three'
    huh['d'] = 'four'
    print huh

우리에게 주어지다:

{
  'a': 'one',
  'b': 'two',
  'c': 'three',
  'd': 'four',
  'huh': {...},
  '__module__': '__main__',
}

지금까지 내가 말한 모든 내용 locals()도 마찬가지입니다 vars()... 차이점 vars()은 다음과 같습니다 . 단일 객체를 인수로 받아들이고 객체를 제공하면 해당 객체의 객체를 반환 __dict__합니다. 일반적인 객체의 __dict__경우 대부분의 속성 데이터가 저장되는 위치입니다. 여기에는 클래스 변수 및 모듈 전역이 포함됩니다.

class Test(object):
    a = 'one'
    b = 'two'
    def frobber(self):
        print self.c
t = Test()
huh = vars(t)
huh['c'] = 'three'
t.frobber()

그것은 우리에게 :

three

함수 __dict__는 로컬 변수가 아닌 속성 네임 스페이스입니다. __dict__재귀와 멀티 스레딩은 각각 고유 한 지역 변수를 사용하여 동시에 함수를 여러 번 호출 할 수 있기 때문에 함수가 지역 변수를 저장 하는 것은 의미가 없습니다 .

def f(outer):
    if outer:
        f(False)
        print('Outer call locals:', locals())
        print('f.__dict__:', f.__dict__)
    else:
        print('Inner call locals:', locals())
        print('f.__dict__:', f.__dict__)

f.x = 3

f(True)

그것은 우리에게 :

Inner call locals: {'outer': False}
f.__dict__: {'x': 3}
Outer call locals: {'outer': True}
f.__dict__: {'x': 3}

여기서는 f재귀 적으로 호출되므로 내부 및 외부 호출이 겹칩니다. 이 호출 할 때 각자는 자신의 지역 변수를 볼 수 locals()있지만, 두 호출은 동일한 참조 f.__dict__하고, f.__dict__그 안에있는 지역 변수가 없습니다.


4
"및 사전에 할당 된 부분은 실제 로컬 네임 스페이스에 반영되지 않습니다"라는 부분 은 다소 명확 하게 표현 될 수 있습니다 .
Sven Marnach

이상하게도 를 사용하면 함수 내에서 호출 된 vars()또는 locals()사전에 추가 된 변수에 액세스 할 수 있습니다 eval(). EG : 실행될 def test(): huh = locals(); huh['d'] = 4; print eval('d')때 4를 인쇄합니다 test()!
Mark Mikofski

1
실제로 dict(로 반환 locals()) 에 대한 할당 은 로컬 네임 스페이스에 반영되고 로컬 네임 스페이스에 대한 변경 사항은 dict(내 파이썬에서)에 반영됩니다 . 유일한 것은 사양이이 동작을 보장하지는 않는다는 것입니다.
skyking

네임 네임 보다 용어 이름 범위 사용법이 더 쉬워 보입니다 .
overexchange

1
@overexchange : import this그리고 구글에서site:docs.python.org namespace
Ethan Furman
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.