Chinaunix首页 | 论坛 | 博客
  • 博客访问: 393747
  • 博文数量: 53
  • 博客积分: 1910
  • 博客等级: 中尉
  • 技术积分: 1130
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-10 14:56
文章分类

全部博文(53)

文章存档

2013年(1)

2012年(17)

2011年(33)

2010年(2)

分类: Python/Ruby

2012-04-20 00:46:21

假设在3个嵌套域里执行exec
大概就是下面的意思
ns 是最上层域,接下来是ns1 是ns的子域, ns11是ns1的子域
直接exec in 代码如下:

点击(此处)折叠或打开

  1. ns = {}
  2. ns1 = {}
  3. ns11 = {}
  4. exec ('a=1+2') in ns
  5. exec ('b=a+1') in ns,ns1
  6. 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 类,并重载字典的的上面几个方法:
代码如下:

点击(此处)折叠或打开

  1. lass scope(dict):
  2.     def __init__(self,parent=None):
  3.         self.parent = parent
  4.         self.scope = {}

  5.     def __setitem__(self, key, value):
  6.         #print "setitem", key, value
  7.         self.scope[key] = value
  8.     
  9.     def __getitem__(self, key):
  10.         cur_scope = self.scope
  11.         cur_parent = self.parent
  12.         while not cur_scope.has_key(key):
  13.             if cur_parent == None:
  14.                 raise KeyError(key)
  15.                 #break
  16.             else:
  17.                 cur_scope = cur_parent.scope
  18.                 cur_parent = cur_parent.parent
  19.             
  20.         return cur_scope[key]


  21.     def __delitem__(self, key):
  22.         del self.__dict__[key]


  23.     def __getattr__(self, key): # Automatically called when the attribute name is accessed and the object has no such attribute (not in __dict__)
  24.             return self.__getitem__(key)

  25.     def dump(self):
  26.         print self.scope

执行代码:

点击(此处)折叠或打开

  1. ns = scope()
  2. ns1 = scope(ns)
  3. ns11 = scope(ns1)
  4. exec ('a=1+2') in globals(),ns
  5. exec ('b=a+1') in globals(),ns1
  6. exec ('c=a+b') in globals(),ns11
  7. print ns11.c
  8. ns.dump()
  9. ns1.dump()
  10. ns11.dump()

  11. 执行结果如下:

  12. 7
  13. {'a': 3}
  14. {'b': 4}
  15. {'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
代码如下:

 

点击(此处)折叠或打开

  1. class scope(dict):
  2.     def __init__(self,parent=None):
  3.         self._unlock()
  4.         self.parent = parent
  5.         self.scope = {}
  6.         self._lock()

  7.     def __setitem__(self, key, value):
  8.         self._unlock()
  9.         #print "set item", key, value
  10.         self.scope[key] = value
  11.         self._lock()
  12.     
  13.     def __getitem__(self, key):
  14.         self._unlock()

  15.         cur_scope = self.scope
  16.         cur_parent = self.parent
  17.         while not cur_scope.has_key(key):
  18.             if cur_parent == None:
  19.                 raise KeyError(key)
  20.                 #break
  21.             else:
  22.                 cur_scope = cur_parent.scope
  23.                 cur_parent = cur_parent.parent
  24.             
  25.         self._lock()
  26.         return cur_scope[key]

  27.     def __delitem__(self, key):
  28.         del self.__dict__[key]

  29.     def __setattr__(self, key, value):
  30.         if self.__dict__['locked'] is True:
  31.             self.__setitem__(key,value)
  32.         else:
  33.             print "setattr", key, value
  34.             self.__dict__[key] = value
  35.     
  36.     def __getattr__(self, key):
  37.         if self.__dict__['locked'] is True:
  38.             return self.__getitem__(key)
  39.         else:
  40.             return self.__dict__[key]

  41.     def dump(self):
  42.         self._unlock()
  43.         print self.scope
  44.         self._lock()

  45.     def _lock(self):
  46.         self.__dict__['locked'] = True

  47.     def _unlock(self):
  48.         self.__dict__['locked'] = False


  49. 执行正常
  50. ns = scope()
  51. ns1 = scope(ns)
  52. ns11 =scope(ns1)
  53. exec ('a=1+2') in globals(),ns
  54. exec ('b=a+1') in globals(),ns1
  55. exec ('c=a+b') in globals(),ns11
  56. print ns11.c

  57. ns.dump()
  58. ns1.dump()
  59. ns11.dump()
  60. 结果和上面一样
  61. 7
  62. {'a': 3}
  63. {'b': 4}
  64. {'c': 7}

  65. 执行ns.a = 4
  66. ns.dump()
  67. {'a': 4}



基本就是把__ditc__中的属性和self.scope = {}中域的属性分开,然后__ditc__中的属性只能在内部访问
这样__getitem__中cur_scope = self.scope的self.scope 访问在内部时是unlock的,就去访问__dict__去了
不会再recurse。

结束

 


阅读(2002) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~