假设在3个嵌套域里执行exec
大概就是下面的意思
ns 是最上层域,接下来是ns1 是ns的子域, ns11是ns1的子域
直接exec in 代码如下:
- ns = {}
- ns1 = {}
- ns11 = {}
- exec ('a=1+2') in ns
- exec ('b=a+1') in ns,ns1
- exec ('c=a+b') in ns,ns1,ns11 # error
根据exec in的语法 :exec [in globaldict [, localdict]]
最后一句不行
但如果 改为exec ('c=a+b') in ns,ns11
报NameError: name 'b' is not defined
因为ns1 域没有,所以ns1 域中的b 找不到
如何解决?先复习下字典的几个method:
# __getattribute__(self, name): Automatically called when the attribute name is accessed.
# __getattr__(self, name): Automatically called when the attribute name is accessed and the object has no such attribute.
# __setattr__(self, name, value): Automatically called when an attempt is made to bind the attribute name to value.
# __delattr__(self, name): Automatically called when an attempt is made to delete the attribute name.
定义一个新scope 类,并重载字典的的上面几个方法:
代码如下:
- lass scope(dict):
- def __init__(self,parent=None):
- self.parent = parent
- self.scope = {}
- def __setitem__(self, key, value):
- #print "setitem", key, value
- self.scope[key] = value
-
- def __getitem__(self, key):
- cur_scope = self.scope
- cur_parent = self.parent
- while not cur_scope.has_key(key):
- if cur_parent == None:
- raise KeyError(key)
- #break
- else:
- cur_scope = cur_parent.scope
- cur_parent = cur_parent.parent
-
- return cur_scope[key]
- def __delitem__(self, key):
- del self.__dict__[key]
- def __getattr__(self, key): # Automatically called when the attribute name is accessed and the object has no such attribute (not in __dict__)
- return self.__getitem__(key)
- def dump(self):
- print self.scope
执行代码:
- ns = scope()
- ns1 = scope(ns)
- ns11 = scope(ns1)
- exec ('a=1+2') in globals(),ns
- exec ('b=a+1') in globals(),ns1
- exec ('c=a+b') in globals(),ns11
- print ns11.c
- ns.dump()
- ns1.dump()
- ns11.dump()
- 执行结果如下:
- 7
- {'a': 3}
- {'b': 4}
- {'c': 7}
到这里基本完成需求了, 多此1举,输入下面命令:
ns.a =4
ns.dump()
{'a': 3}
ns 中的 a 还是3 ,
输入
ns.__dict__
{'a': 4, 'scope': {'a': 3}, 'parent': None}
发觉 ns.a =4 ,其实放到字典的属性中去了, (__setattr__)
如果执行
ns['a'] = 4
ns.dump()
{'a': 4}
虽然有歧义,似乎重载__setattr就可以了,可以吗?
在上面scope 类最后加入方法:
def __setattr__(self, key, value): #Automatically called when an attempt is made to bind the attribute name to value
self.__setitem__(key,value)
完了
执行:
错误长达100多行,就不贴出来了,
错误原因看下,__init__中有对instance 属性的设置,比如self.scope = {}, 然后__setattr__却又被重载为__setitem__
当执行__getitem__ method 的cur_scope = self.scope 因为需要self.scope 就去 __getattr__ method 调 __getitem__
递归了,好在python 有recursion depth,否则上个厕所回来,程序还在执行
看来这个消除歧义尤佳也挺麻烦的,加个lock
代码如下:
- class scope(dict):
- def __init__(self,parent=None):
- self._unlock()
- self.parent = parent
- self.scope = {}
- self._lock()
- def __setitem__(self, key, value):
- self._unlock()
- #print "set item", key, value
- self.scope[key] = value
- self._lock()
-
- def __getitem__(self, key):
- self._unlock()
- cur_scope = self.scope
- cur_parent = self.parent
- while not cur_scope.has_key(key):
- if cur_parent == None:
- raise KeyError(key)
- #break
- else:
- cur_scope = cur_parent.scope
- cur_parent = cur_parent.parent
-
- self._lock()
- return cur_scope[key]
- def __delitem__(self, key):
- del self.__dict__[key]
- def __setattr__(self, key, value):
- if self.__dict__['locked'] is True:
- self.__setitem__(key,value)
- else:
- print "setattr", key, value
- self.__dict__[key] = value
-
- def __getattr__(self, key):
- if self.__dict__['locked'] is True:
- return self.__getitem__(key)
- else:
- return self.__dict__[key]
- def dump(self):
- self._unlock()
- print self.scope
- self._lock()
- def _lock(self):
- self.__dict__['locked'] = True
- def _unlock(self):
- self.__dict__['locked'] = False
- 执行正常
- ns = scope()
- ns1 = scope(ns)
- ns11 =scope(ns1)
- exec ('a=1+2') in globals(),ns
- exec ('b=a+1') in globals(),ns1
- exec ('c=a+b') in globals(),ns11
- print ns11.c
- ns.dump()
- ns1.dump()
- ns11.dump()
- 结果和上面一样
- 7
- {'a': 3}
- {'b': 4}
- {'c': 7}
- 执行ns.a = 4
- ns.dump()
- {'a': 4}
基本就是把__ditc__中的属性和self.scope = {}中域的属性分开,然后__ditc__中的属性只能在内部访问
这样__getitem__中cur_scope = self.scope的self.scope 访问在内部时是unlock的,就去访问__dict__去了
不会再recurse。
结束
阅读(2102) | 评论(0) | 转发(0) |