program tip

파이썬에서 globals ()에 대한 이유?

radiobox 2020. 11. 27. 07:59
반응형

파이썬에서 globals ()에 대한 이유?


파이썬에서 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()

그러나 이름이 같은 두 개의 변수가 있고 같은 범위 내에서 둘 다 사용해야하는 문제가 발생해서는 안됩니다.


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

그이면의 근거 locals()는 함수에 정의 된 변수 dir를 보는 데 사용 하거나 모듈의 내용 또는 객체의 속성 을 보는 데 사용하는 것과 동일 합니다.

C ++ 배경에서 왔기 때문에 이러한 것들이 불필요 해 보인다는 것을 이해할 수 있습니다. 정적으로 링크되고 정적으로 형식화 된 환경에서는 절대적으로 그렇습니다. 이 경우 컴파일 타임에 정확히 어떤 변수가 전역 변수인지, 객체가 어떤 멤버를 가질 지, 심지어 다른 컴파일 단위에서 어떤 이름을 내보냈는지 알 수 있습니다.

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


함수의 문자열 이름을 사용하여 함수를 호출해야 할 때도 유용합니다. 예를 들면 :

def foo():
    pass

function_name_as_string = 'foo'

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

당신의 결과를 전달할 수 globals()locals()받는 사람 eval, execfile그리고 __import__명령을. 이렇게하면 해당 명령이 작동 할 수있는 제한된 환경이 생성됩니다.

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


globals()유용합니다 eval()- 당신은 범위 변수를 참조하는 어떤 코드를 평가하려면, 그 변수 중 전역 또는 지역 주민에있을 것입니다.


조금 확장하기 위해 eval()내장 함수는 주어진 파이썬 코드 문자열을 해석합니다. 서명은이며 다음 eval(codeString, globals, locals)과 같이 사용합니다.

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

인터프리터가 변수 사전 x에서 값을 가져 오기 때문에 작동 locals()합니다. 물론 eval에 고유 한 변수 사전을 제공 할 수 있습니다.


'선언적 파이썬'에서 유용 할 수 있습니다. 예를 들어, 아래에서 FooDefBarDef클래스 다음 입력, 또는 그 구성과 일부 패키지에서 사용되는 데이터 구조의 연속을 정의하는 데 사용된다. 이를 통해 입력 내용에 많은 유연성을 제공하고 파서를 작성할 필요가 없습니다.

# 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')

Note that this configuration file uses a loop to build up a list of names which are part of the configuration of Foo_other. So, this configuration language comes with a very powerful 'preprocessor', with an available run-time library. In case you want to, say, find a complex log, or extract things from a zip file and base64 decode them, as part of generating your configuration (this approach is not recommended, of course, for cases where the input may be from an untrusted source...)

The package reads the configuration using something like the following:

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

So, finally getting to the point, globals() is useful, when using such a package, if you want to mint a series of definitions procedurally:

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

This is equivalent to writing out

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 ...

An example of a package which obtains its input by gathering a bunch of definitions from a python module is PLY (Python-lex-yacc) http://www.dabeaz.com/ply/ -- in that case the objects are mostly function objects, but metadata from the function objects (their names, docstrings, and order of definition) also form part of the input. It's not such a good example for use of globals() . Also, it is imported by the 'configuration' - the latter being a normal python script -- rather than the other way around.

I've used 'declarative python' on a few projects I've worked on, and have had occasion to use globals() when writing configurations for those. You could certainly argue that this was due to a weakness in the way the configuration 'language' was designed. Use of globals() in this way doesn't produce very clear results; just results which might be easier to maintain than writing out a dozen nearly-identical statements.

You can also use it to give variables significance within the configuration file, according to their names:

# 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")

This method could be useful for any python module that defines a lot of tables and structures, to make it easier to add items to the data, without having to maintain the references as well.


It can also be used to get an instance of the class 'classname' from a string:

class C:
    def __init__(self, x):
        self.x = x
        print('Added new instance, x:', self.x)


def call(str):
    obj = globals()[str](4)
    return obj

c = call('C')
print(c.x)

참고URL : https://stackoverflow.com/questions/12693606/reason-for-globals-in-python

반응형