2017-01-10 29 views
-2

当我传递locals的真实字典时,exec()执行正确的操作并退回到globals字典以查找缺失的名称。但是,如果我将LazyMap(字典型对象)作为本地语言传递,则对全局变量的访问会在给定给LazyMap的lambda中引发一个AttributeError。为什么当变量不在当地人中但是在gl中时,Python3 exec()会引发AttributeError

#!/usr/bin/env python3 

class LazyMap: 
    def __init__(self, keys, getter): 
     self._keys = keys 
     self._getter = getter 

    def keys(self): 
     return self._keys 

    def __getitem__(self, k): 
     return self._getter(k) 

class TestObj: 
    def __init__(self): 
     self.field = 'foo' 

obj = TestObj() 

# this prints 'foo' 
locs = dict((name, getattr(obj, name)) for name in dir(obj)) 
exec('print(field)', globals(), locs) 

# this raises AttributeError 
locs = LazyMap(dir(obj), lambda k,s=obj: getattr(s, k)) 
exec('print(field)', globals(), locs) 

为什么在LazyMap中引发异常,但没有使用纯字典?我如何创建一个局部映射,只有在从exec中访问时才会获取/计算值?

+0

为什么你使用'globals()','exec()'和表面上的'locals()'(尽管我没有看到那个)做你想要实现的任何事情?无论如何,你究竟想要达到什么目的? – TigerhawkT3

+0

我正在创建一个可以用简单的Python单线程编程的文本界面。例如,'d'elete是'rows.pop(cursorRowIndex)',其中'rows'和'cursorRowIndex'都是所示对象的属性。问题是计算了一些属性,可能无效或需要很长时间才能计算。有几十个可用的属性,但没有必要(甚至是有问题的)来计算它们,仅用于当前命令使用的少数几个属性。 – saul

回答

0

我想exec()首先尝试getitem对本地对象,如果一个KeyError被引发,它会退回到全局对象getitem。但是,在给定的代码中,getattr将引发AttributeError而不是KeyError。将传递的lambda更改为vars(s)[k]将导致丢失的键提高正确的KeyError。

总结:__getitem__应该提高KeyError丢失的关键,而__getattr__应该提高AttributeError

相关问题