2009-09-23 3 views

답변

27

이 문제는 다소 Python3 bug list에서 설명합니다. 궁극적으로,이 동작을 얻으려면, 당신이해야 할 :

def foo(): 
    ldict = locals() 
    exec("a=3",globals(),ldict) 
    a = ldict['a'] 
    print(a) 

을 그리고 당신은 the Python3 documentation on exec을 선택하면, 당신은 다음 참고 볼 수 있습니다 : 다시 a specific message on the bug report 참조하면

The default locals act as described for function locals() below: modifications to the default locals dictionary should not be attempted. Pass an explicit locals dictionary if you need to see effects of the code on locals after function exec() returns.

을, 게오르그 브랜는 말한다 :

To modify the locals of a function on the fly is not possible without several consequences: normally, function locals are not stored in a dictionary, but an array, whose indices are determined at compile time from the known locales. This collides at least with new locals added by exec. The old exec statement circumvented this, because the compiler knew that if an exec without globals/locals args occurred in a function, that namespace would be "unoptimized", i.e. not using the locals array. Since exec() is now a normal function, the compiler does not know what "exec" may be bound to, and therefore can not treat is specially.

강조는 내 것입니다.

그래서 요점은 이 아닌 로컬 변수 사용을 더 잘 최적화 할 수 있다는 것입니다. 기본적으로이 동작이 허용됩니다. 당신이 방법 안에있는 경우

Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41) 
[GCC 4.3.3] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> def f(): 
...  a = 1 
...  exec "a=3" 
...  print a 
... 
>>> f() 
3 
+0

파이썬 2.X에서 exec에서 해킹당한 locals() 문제입니다. 이 문제는 분명히 내가 좋아했을만큼 문서화되지 않았습니다. 2.X에서 3.X로 변경되는 Exec/locals는 http://docs.python.org/3.1/library/functions.html#exec 어딘가에서 지적되어야하며 exec는이 최적화를 우회하는 편리한 매개 변수가 있어야한다고 생각합니다. .. – ubershmekel

+0

@MarkRushakoff 임원 라인 구현시 오류가 발생합니다. TypeError : 'dict'객체를 호출 할 수 없습니다. – Leo

+0

@Leo는'dict'가 아닌'ldict'이 아니어야합니까? 어쨌든 파이썬에서는 더 이상 작동하지 않으므로 그렇지 않다면 다른 누군가가 차임 할 것입니다. –

2

, 당신은 그렇게 할 수 있습니다 :

그리고 위의 댓글에서 언급 한 바와 같이 완전성을 위해, 대한

파이썬 2.X에서 예상대로 작업을 수행합니다 :

class Thing(): 
    def __init__(self): 
     exec('self.foo = 2') 

x = Thing() 
print(x.foo) 

You can read more about it here

0

당신이를 사용하여 함수 내에서 지역 변수를 변경할 수없는 이유 그 방법으로 854,026,603,210과 이유가하는 방법은 다음과 같이 요약 할 수있다 exec 행위 :

  1. exec는이 호출되는 가장 안쪽 범위의 범위와 그 지역의 풍경을 공유하는 기능입니다.
  2. 함수 범위 내에서 새 객체를 정의 할 때마다 해당 로컬 네임 스페이스에서 액세스 할 수 있습니다. 즉 local() 사전을 수정합니다. 당신이 exec에 새로운 객체를 정의 할 때 무엇을하는 일은 다음과 거의 동일합니다 :

from copy import copy 
class exec_type: 
    def __init__(self, *args, **kwargs): 
     # default initializations 
     # ... 
     self.temp = copy(locals()) 

    def __setitem__(self, key, value): 
     if var not in locals(): 
      set_local(key, value) 
     self.temp[key] = value 

temp 각 인스턴스 후 리셋 임시 네임 스페이스입니다. (때마다 당신은 호출 exec)


  1. 파이썬은 현지 네임 스페이스의 이름을 찾는 시작합니다. 그것은 LEGB 방식으로 알려져 있습니다. 파이썬은 로컬 네임 스페이스 (namespce)에서 시작하여 엔 클로징 스코프 (Enclosing scope)를 살펴본 다음 글로벌 (Global)을 찾는다. 결국에는 Buit-in 네임 스페이스 내에서 이름을 찾는다.

보다 포괄적 인 예를하고자 다음과 같은 우리 뭔가 :

g_var = 5 

def test(): 
    l_var = 10 
    print(locals()) 
    exec("print(locals())") 
    exec("g_var = 222") 
    exec("l_var = 111") 
    exec("print(locals())") 

    exec("l_var = 111; print(locals())") 

    exec("print(locals())") 
    print(locals()) 
    def inner(): 
     exec("print(locals())") 
     exec("inner_var = 100") 
     exec("print(locals())") 
     exec("print([i for i in globals() if '__' not in i])") 

    print("Inner function: ") 
    inner() 
    print("-------" * 3) 
    return (g_var, l_var) 

print(test()) 
exec("print(g_var)") 

출력 :

{'l_var': 10} 
{'l_var': 10} 
# locals are the same 
{'l_var': 10, 'g_var': 222} 
# after adding g_var and changing the l_var it only adds g_var and left the l_var unchanged 
{'l_var': 111, 'g_var': 222} 
# l_var is changed because we are changing and printing the locals in one instantiation (one call to exec) 
{'l_var': 10, 'g_var': 222} 
{'l_var': 10, 'g_var': 222} 
# In both function's locals and exec's local l_var is unchanged and g_var is added 
Inner function: 
{} 
{'inner_var': 100} 
{'inner_var': 100} 
# inner_function's local is same as exec's local 
['g_var', 'test'] 
# global is only contain g_var and function name (after excluding the special methods) 
--------------------- 

(5, 10) 
5 
관련 문제