星期一, 七月 02, 2007

python several Tree += examples

在设计 += 即 __iadd__ operator overloading 的时候,为保持一致性,另一个操作数只能是 Tree instance 或 Tree dict,那么即要找到不是它们时的边界条件,例如:
>>> tree = reload(tree)
>>> root = tree.Tree(0)
>>> print root

+++ Tree +++
() : 0,
--- Tree ---

>>> root += [1, 2, 3]
debug: AttributeError
Traceback (most recent call last):
File "", line 1, in ?
File "tree.py", line 266, in __iadd__
raise TreeTypeExc(_("Other operand should be a Tree instance or Tree dict"))
tree.TreeTypeExc:
这个 Exception 是由于 AttributeError 被捕捉产生的,因为调用了一个 dict 的 items(),那么定义一个有 items() 的类(多态性):
>>> class temp:
... def __init__(self):
... self.data = 1
... def items(self):
... return self.data
...
>>> t = temp()
>>> t.items()
1
>>> root += t
Traceback (most recent call last):
File "", line 1, in ?
File "tree.py", line 260, in __iadd__
for pathseq, node in other.items():
TypeError: iteration over non-sequence
以及
>>> root += {'a' : 1, 'b' : 2, 'c' : 3}
Traceback (most recent call last):
File "", line 1, in ?
File "tree.py", line 261, in __iadd__
self._1_node_set(pathseq, node())
TypeError: 'int' object is not callable
那么定义一个 callable 的类:
>>> class temp:
... def __init__(self, v):
... self.data = v
... def __call__(self):
... return self.data
...
>>> root += {'a' : temp(1), 'b' : temp(2), 'c' : temp(3)}
>>> print root

+++ Tree +++
() : 0,
('a',) : 1,
('b',) : 2,
('c',) : 3,
--- Tree ---

>>> root += {'' : temp(1), 'b' : temp(2), 'c' : temp(3)}
>>> print root

+++ Tree +++
() : 1,
('a',) : 1,
('b',) : 2,
('c',) : 3,
--- Tree ---

>>> root = tree.Tree(0)
>>> root += {'' : temp(1), 'b' : temp(2), 'c' : temp(3)}
>>> root += {1 : temp(1), 'b' : temp(2), 'c' : temp(3)}
Traceback (most recent call last):
File "", line 1, in ?
File "tree.py", line 261, in __iadd__
self._1_node_set(pathseq, node())
File "tree.py", line 333, in _1_node_set
next = pathseq[0]
TypeError: unsubscriptable object

>>> root += {tree.Tree(1): temp(1), 'b' : temp(2), 'c' : temp(3)}
Traceback (most recent call last):
File "", line 1, in ?
TypeError: unhashable instance

>>> root = tree.Tree(0)
>>> root += {'' : temp(1), 'b' : temp(2), 'c' : temp(3)}
>>> print root

+++ Tree +++
() : 1,
('b',) : 2,
('c',) : 3,
--- Tree ---
所以基本上可以看到,只有两个异常是需要注意的,即:TypeError 和 AttributeError,最终成品如下:
def __iadd__(self, other):
try:
self.__update__(other)
except TreeTypeExc:
try:
for pathseq, node in other.items():
self._one_node_set(pathseq, node())
except TreeExc, trx:
# print "debug: TreeExc"
raise TreeTypeExc(trx.msg)
except (AttributeError, TypeError):
# print "debug: AttributeError or TypeError"
raise TreeTypeExc(_("Other operand should be a Tree instance or Tree dict"))
return self
因为 'b' 和 ('b',) 都是 sequence,所以两种效果一样(对 "" 和 () 同理),但 'abc' 和 ('abc',) 是不同的。

现在 Tree 的基本结构已经全部完成,可以从我的项目的 SVN 检出。

没有评论: