2009-06-25 2 views
29

이 조각을 고려해현재 범위에있는 모든 변수의 DICT를 확인하고 그 값

globalVar = 25 

def myfunc(paramVar): 
    localVar = 30 
    print "Vars: {globalVar}, {paramVar}, {localVar}!".format(**VARS_IN_SCOPE) 

myfunc(123) 

어디 VARS_IN_SCOPE 나는 그 이후 해요 DICT는 다른 것들 사이 globalVar, paramVarlocalVar을 포함 할 것입니다.

기본적으로 현재 문자열 내에있는 모든 변수를 참조 할 수 있습니다. 따라서 예상되는 출력은 다음과 같습니다 나는 format()**dict(globals().items() + locals().items())를 전달하여이를 달성 할 수

Vars: 25, 123, 30

. 이것이 항상 올바른가, 아니면이 표현식이 잘못 처리 할 수있는 몇 가지 코너 케이스가 있습니까?

질문을 명확히하기 위해 다시 작성하십시오.

+0

왜 그렇게하고 싶습니까? 기회는 무엇이든 할 수있는 더 좋은 방법입니다. –

+0

나는 그 발췌 문장이 그것을 명확하게 만들 것이라고 생각했다. 문자열 내부 변수를 보간하고 싶습니다. 꼭 좋은 방법이있을 수 있습니다. 언제든지 대답으로 제안하십시오. –

+0

죄송합니다, 발췌 문장은 설명하지 않습니다 ** ** 왜 그런 일이 필요합니다. 또한 매개 변수는 단순히 로컬이므로 별도의 범위가 아닙니다. –

답변

32

가장 좋은 방법은 dict(globals(), **locals())입니다.

전역 변수와 지역 변수를 병합하는 방법이 없다면 (a) 내장 변수가 있습니다. (즉, 내장 변수를 "변수"라고 생각하지 않는다고 생각합니다. 그러나 변수를 선택하면 ! -), 그리고 (b) 중첩 된 함수 인 경우 함수를 포함하는 함수에 로컬 인 모든 변수 (의 모든 값을 가진 사전을 얻는 데 실제로 좋은 방법은 없습니다. 중첩 된 함수, 즉 "자유 변수"는 클로저에서 세포처럼 생존한다.

나는이 문제가 당신의 의도 된 용도에별로 중요하지 않다고 생각하지만, 당신은 "코너 케이스"를 언급했다 ;-). 그것들을 감추고 싶다면, 모든 셀 (네스트 함수에서 명시 적으로 언급 한 변수들 - thefunction.func_code.co_freevars)을 사용하여 내장 된 셀을 쉽게 얻을 수있는 방법과 쉬운 셀을 얻는 방법이 있습니다. 셀을 얻으려면 thefunction.func_closure, 값을 얻으려면 각 셀에 cell_contents). (그러나 중첩 함수의 코드에서 이 명시 적으로 액세스 된 인 함수를 포함하는 변수 일뿐입니다!).

+0

중첩 된 함수 내부에서 모든 변수를 가져올 수 없다는 것은 이상한 일입니다. 누구나'locals()'가 작동하지 않는 이유를 아는 사람이 있습니까? 그것이해야하는 것처럼 보인다! – sudo

7

의도 한대로입니까? 내가 제대로 설명서를 읽어 보면

d = dict(globals()) 
d.update(locals()) 

, 당신은 당신이 locals() 어쨌든, 당신의 범위 내에서 환경 설정을해야하기 때문에 locals() DICT (에서 중복 된 삽입 새 항목을 덮어의 globals() DICT의 복사본을 생성).


나는 기능을 호출 의 범위에서 변수의 전체 사전을 반환하는 적절한 기능을 얻기에 어떤 운이 없었어요.

from pprint import * 

def allvars_bad(): 
    fake_temp_var = 1 
    d = dict(globals()) 
    d.update(locals()) 
    return d 

def foo_bad(): 
    x = 5 
    return allvars_bad() 

def foo_good(): 
    x = 5 
    fake_temp_var = "good" 
    d = dict(globals()) 
    d.update(locals()) 
    return d 

pprint (foo_bad(), width=50) 
pprint (foo_good(), width=50) 

출력 : 여기에 코드입니다 (난 단지 SO 멋지게 출력 형식을 pprint을 사용) 두 번째 출력에, 우리는 fake_temp_var을 덮어 것을

{'PrettyPrinter': <class pprint.PrettyPrinter at 0xb7d316ec>, 
'__builtins__': <module '__builtin__' (built-in)>, 
'__doc__': None, 
'__file__': 'temp.py', 
'__name__': '__main__', 
'__package__': None, 
'allvars_bad': <function allvars_bad at 0xb7d32b1c>, 
'd': <Recursion on dict with id=3084093748>, 
'fake_temp_var': 1, 
'foo_bad': <function foo_bad at 0xb7d329cc>, 
'foo_good': <function foo_good at 0xb7d32f0c>, 
'isreadable': <function isreadable at 0xb7d32c34>, 
'isrecursive': <function isrecursive at 0xb7d32c6c>, 
'pformat': <function pformat at 0xb7d32bc4>, 
'pprint': <function pprint at 0xb7d32b8c>, 
'saferepr': <function saferepr at 0xb7d32bfc>} 
{'PrettyPrinter': <class pprint.PrettyPrinter at 0xb7d316ec>, 
'__builtins__': <module '__builtin__' (built-in)>, 
'__doc__': None, 
'__file__': 'temp.py', 
'__name__': '__main__', 
'__package__': None, 
'allvars_bad': <function allvars_bad at 0xb7d32b1c>, 
'd': <Recursion on dict with id=3084093884>, 
'fake_temp_var': 'good', 
'foo_bad': <function foo_bad at 0xb7d329cc>, 
'foo_good': <function foo_good at 0xb7d32f0c>, 
'isreadable': <function isreadable at 0xb7d32c34>, 
'isrecursive': <function isrecursive at 0xb7d32c6c>, 
'pformat': <function pformat at 0xb7d32bc4>, 
'pprint': <function pprint at 0xb7d32b8c>, 
'saferepr': <function saferepr at 0xb7d32bfc>, 
'x': 5} 

참고하고, x는 선물; 첫 번째 출력은 allvars_bad 범위 내의 로컬 변수 만 포함합니다.

그래서 전체 변수 범위에 액세스하려는 경우 locals()를 다른 함수 안에 넣을 수 없습니다.


나는 어떤 종류의 프레임 개체가 있다고 의심했지만, 그 프레임을 찾지 못했습니다.

이것은 당신의 사양에 작동

, 저는 믿습니다 :

def allvars_good(offset=0): 
    frame = sys._getframe(1+offset) 
    d = frame.f_globals 
    d.update(frame.f_locals) 
    return d 


def foo_good2(): 
    a = 1 
    b = 2 
    return allvars_good() 

->

{'PrettyPrinter': <class pprint.PrettyPrinter at 0xb7d6474c>, 
'__builtins__': <module '__builtin__' (built-in)>, 
'__doc__': None, 
'__file__': 'temp.py', 
'__name__': '__main__', 
'__package__': None, 
'a': 1, 
'allvars_bad': <function allvars_bad at 0xb7d65b54>, 
'allvars_good': <function allvars_good at 0xb7d65a04>, 
'b': 2, 
'foo_bad': <function foo_bad at 0xb7d65f44>, 
'foo_good': <function foo_good at 0xb7d65f7c>, 
'foo_good2': <function foo_good2 at 0xb7d65fb4>, 
'isreadable': <function isreadable at 0xb7d65c6c>, 
'isrecursive': <function isrecursive at 0xb7d65ca4>, 
'pformat': <function pformat at 0xb7d65bfc>, 
'pprint': <function pprint at 0xb7d65bc4>, 
'saferepr': <function saferepr at 0xb7d65c34>, 
'sys': <module 'sys' (built-in)>} 
+0

귀하의 질문에 대답하기 위해, 나는 몰라 :) 이것은 실제로 내가 뭘 찾고 싶습니다 - 단지 두 가지를 결합하는 것이 옳은 일인지 여부입니다. –

+0

그래, 불행히도 현지인()이 바로 거기에 있어야합니다. globals()와 비슷하게 작동하려면 동일한 모듈에 있어야합니다. sys._getframe() 속임수가 대신 사용될 수 있는지 궁금합니다. –

2

당신은 당신의 자신의 만들 수 :

allvars = dict() 
allvars.update(globals()) 
allvars.update(locals()) 

또는 결합 첫 두 줄을 :

allvars = dict(globals()) 
allvars.update(locals()) 
1

문자열로 보간하는 것이 가장 간단한 방법으로 작동합니다. 변수를 나열하십시오. 파이썬은 로컬과 전역을 검사합니다. 당신은 (지역 주민 무시 전역으로)하고있는로 두 dicts을 병합

globalVar = 25 

def myfunc(paramVar): 
    localVar = 30 
    print "Vars: %d, %d, %d!" % (globalVar, paramVar, localVar) 

myfunc(123) 
+0

그것은 보간법이 아닙니다. http://en.wikipedia.org/wiki/Variable_(computer_science)#Interpolation - 파이썬에는 이와 같은 것이 없지만 .format() 함수를 사용하면 꽤 가까워 질 수 있습니다. –

+0

그리고 내가 왜 싫어하는지 궁금한 경우에는 다음과 같이 생각하십시오 : print "{path} /myscript.py-input {path}/file1 --output {path}/file2".format (** locals ()) - "%"를 사용하면 경로를 세 번 통과해야합니다. 변수가 많으면 유지 관리에 악몽이됩니다. –

+0

@romkyns : 그렇지 않습니다. 문자열'%'연산자는 dict 인수를 취할 수 있으며'** '는'format'으로 압축을 풀 필요가 없습니다 : print "% (path) s/myscript.py --input % (path) s/file1 "--output % (path) s/file2"% locals() –

2
globalVar = 25 

def myfunc(paramVar): 
    localVar = 30 
    all_vars = locals.copy() 
    all_vars.update(globals()) 
    print "Vars: {globalVar}, {paramVar}, {localVar}!".format(all_vars) 

myfunc(123) 
관련 문제