class DBDB(object): def __init__(self, f): self._storage = Storage(f) #_storage在DBDB中只完成一个功能:检查文件有没有关闭 self._tree = BinaryTree(self._storage) def _assert_not_close(self): if self._storage.closed: raise ValueError('Database closed.') def close(self): self._storage.close() def commit(self): self._assert_not_close() self._tree.commit() #实现__getitem__、__setitem__、__delitem__、__contains__等函数, # 就能像操作词典一样操作DBDB对象了 def __getitem__(self, key): '''通过 dbdb[key] 获取键值''' self._assert_not_close() return self._tree.get(key) def __setitem__(self, key, value): '''通过 dbdb[key] = value 设置键值''' self._assert_not_close() return self._tree.set(key, value) def __delitem__(self, key): '''通过 del dbdb[key] 删除键值''' self._assert_not_close() return self._tree.pop(key) def __contains__(self, key): '''通过 key in dbdb 来判断键在不在数据库中''' try: self[key] except KeyError: return False else: return True def __len__(self): return len(self._tree)
class DBDB(object): def __init__(self, f): self._storage = Storage(f) self._tree = BinaryTree(self._storage) def _assert_not_closed(self): if self._storage.closed: raise ValueError('Database closed.') def close(self): self._storage.close() def commit(self): self._assert_not_closed() self._tree.commit() def __getitem__(self, key): #通过db[key] 获取键值 self._assert_not_closed() return self._tree.get(key) def __setitem__(self, key, value): #通过db[key] =value 设置键值 self._assert_not_closed() return self._tree.set(key, value) def __delitem__(self, key): #通过 del db[key] 删除键值 self._assert_not_closed() return self._tree.pop(key) def __contains__(self, key): #通过key in db 来判断键在不在数据库中 try: self[key] except KeyError: return False else: return True def __len__(self): return len(self._tree)
class DBDB(object): def __init__(self, f): self._storage = Storage(f) self._tree = BinaryTree(self._storage) def _assert_not_closed(self): if self._storage.closed: raise ValueError('Database closed.') def close(self): self._storage.close() def commit(self): self._assert_not_closed() self._tree.commit() #相当于重写了字典中的getitem函数 def __getitem__(self, key): self._assert_not_closed() return self._tree.get(key) def __setitem__(self, key, value): self._assert_not_closed() return self._tree.set(key, value) def __delitem__(self, key): self._assert_not_closed() return self._tree.pop(key) def __contains__(self, key): try: self[key] except KeyError: return False else: return True def __len__(self): return len(self._tree)
class DBDB(object): def __init__(self, f): self._storage = Storage(f) # Reference to storage so it can enforce preconditions self._tree = BinaryTree(self._storage) def _assert_not_closed(self): if self._storage.closed: raise ValueError('Database closed.') def close(self): self._storage.close() def commit(self): self._assert_not_closed() self._tree.commit() # Implements dict functions def __getitem__(self, key): # operator [<key>] self._assert_not_closed() return self._tree.get(key) def __setitem__(self, key, value): # operator [<new_key>] = <value> self._assert_not_closed() return self._tree.set(key, value) def __delitem__(self, key): # operator del dict[<key>] self._assert_not_closed() return self._tree.pop(key) def __contains__(self, key): # operator <key> in dict try: self[key] except KeyError: return False else: return True def __len__(self): return len(self._tree)
class DBDB(object): def __init__(self, f): self._storage = Storage(f) self._tree = BinaryTree(self._storage) def _assert_not_closed(self): if self._storage.closed: raise ValueError("Database Closed!") def close(self): self._storage.close() def commit(self): self._assert_not_closed() self._tree.commit() def __getitem__(self, key): self._assert_not_closed() return self._tree.get(key) def __setitem__(self, key, value): self._assert_not_closed() return self._tree.set(key, value) def __delitem__(self, key): self._assert_not_closed() return self._tree.pop(key) def __contains__(self, key): try: #self[key]的用法不懂,奇怪的用法 self[key] except KeyError: return False else: return True def __len__(self): return len(self._tree)
class TestBinaryTree(object): def setup(self): self.f = tempfile.NamedTemporaryFile(delete=False) self.storage = Storage(self.f) self.tree = BinaryTree(self.storage) def teardown(self): pass def test_get_missing_key_raises_key_error(self): with assert_raises(KeyError): self.tree.get('Not A Key In The Tree') def test_set_and_get_key(self): self.tree.set('b', '1') self.tree.set('a', '2') self.tree.set('c', '3') self.tree.commit() eq_(self.tree.get('a'), '2') eq_(self.tree.get('b'), '1') eq_(self.tree.get('c'), '3') def test_set_and_reset_key(self): self.tree.set('a', '1') eq_(self.tree.get('a'), '1') self.tree.set('a', '2') eq_(self.tree.get('a'), '2') def test_delete_a_non_key(self): with assert_raises(KeyError): self.tree.pop('a') def test_set_and_delete_key(self): self.tree.set('a', '1') self.tree.set('b', '2') self.tree.set('c', '3') self.tree.commit() eq_(self.tree.get('a'), '1') eq_(self.tree.get('b'), '2') eq_(self.tree.get('c'), '3') self.tree.pop('a') eq_(self.tree.get('b'), '2') eq_(self.tree.get('c'), '3') with assert_raises(KeyError): self.tree.get('a') def test_set_and_delete_left_node(self): self.tree.set('b', '2') self.tree.set('a', '1') self.tree.set('c', '3') self.tree.commit() eq_(self.tree.get('a'), '1') eq_(self.tree.get('b'), '2') eq_(self.tree.get('c'), '3') self.tree.pop('a') eq_(self.tree.get('b'), '2') eq_(self.tree.get('c'), '3') with assert_raises(KeyError): self.tree.get('a') def test_set_and_delete_right_node(self): self.tree.set('b', '2') self.tree.set('a', '1') self.tree.set('c', '3') self.tree.commit() eq_(self.tree.get('a'), '1') eq_(self.tree.get('b'), '2') eq_(self.tree.get('c'), '3') self.tree.pop('c') eq_(self.tree.get('a'), '1') eq_(self.tree.get('b'), '2') with assert_raises(KeyError): self.tree.get('c') def test_set_and_delete_root_node(self): self.tree.set('b', '2') self.tree.set('a', '1') self.tree.set('c', '3') self.tree.commit() eq_(self.tree.get('a'), '1') eq_(self.tree.get('b'), '2') eq_(self.tree.get('c'), '3') self.tree.pop('b') eq_(self.tree.get('a'), '1') eq_(self.tree.get('c'), '3') with assert_raises(KeyError): self.tree.get('b') def test_set_and_delete_root_node_without_its_left_node(self): self.tree.set('b', '2') self.tree.set('c', '3') self.tree.commit() eq_(self.tree.get('b'), '2') eq_(self.tree.get('c'), '3') self.tree.pop('b') eq_(self.tree.get('c'), '3') with assert_raises(KeyError): self.tree.get('b') def test_set_and_delete_root_node_without_its_right_node(self): self.tree.set('b', '2') self.tree.set('a', '1') self.tree.commit() eq_(self.tree.get('b'), '2') eq_(self.tree.get('a'), '1') self.tree.pop('b') eq_(self.tree.get('a'), '1') with assert_raises(KeyError): self.tree.get('b') def test_set_and_delete_root_node_with_its_left_part_needs_to_findmax( self): self.tree.set('e', '5') self.tree.set('a', '1') self.tree.set('b', '2') self.tree.set('c', '3') self.tree.set('f', '6') self.tree.commit() self.tree.pop('e') with assert_raises(KeyError): self.tree.get('e')
class TestBinaryTree(object): def setup(self): self.tree = BinaryTree(StubStorage()) def test_get_missing_key_raises_key_error(self): with assert_raises(KeyError): self.tree.get('Not A Key In The Tree') def test_set_and_get_key(self): self.tree.set('a', 'b') eq_(self.tree.get('a'), 'b') def test_random_set_and_get_keys(self): ten_k = list(range(10000)) pairs = list(zip(random.sample(ten_k, 10), random.sample(ten_k, 10))) for i, (k, v) in enumerate(pairs, start=1): self.tree.set(k, v) eq_(len(self.tree), i) for k, v in pairs: eq_(self.tree.get(k), v) random.shuffle(pairs) for i, (k, v) in enumerate(pairs, start=1): self.tree.pop(k) eq_(len(self.tree), len(pairs) - i) def test_overwrite_and_get_key(self): self.tree.set('a', 'b') self.tree.set('a', 'c') eq_(self.tree.get('a'), 'c') def test_pop_non_existent_key(self): with assert_raises(KeyError): self.tree.pop('Not A Key In The Tree') def test_del_leaf_key(self): self.tree.set('b', '2') self.tree.pop('b') with assert_raises(KeyError): self.tree.get('b') def test_del_left_node_key(self): self.tree.set('b', '2') self.tree.set('a', '1') self.tree.pop('b') with assert_raises(KeyError): self.tree.get('b') self.tree.get('a') def test_del_right_node_key(self): self.tree.set('b', '2') self.tree.set('c', '3') self.tree.pop('b') with assert_raises(KeyError): self.tree.get('b') self.tree.get('c') def test_del_full_node_key(self): self.tree.set('b', '2') self.tree.set('a', '1') self.tree.set('c', '3') self.tree.pop('b') with assert_raises(KeyError): self.tree.get('b') self.tree.get('a') self.tree.get('c')
class TestBinaryTree: def setup(self): self.tree = BinaryTree(StubStorage()) def test_get_missing_key_raises_key_error(self): with assert_raises(KeyError): self.tree.get("Not a key in the tree") def test_set_and_get_key(self): self.tree.set("a", "b") eq_(self.tree.get("a"), "b") def test_random_set_and_get_keys(self): ten_k = list(range(10000)) pairs = list(zip(random.sample(ten_k, 10), random.sample(ten_k, 10))) for i, (k, v) in enumerate(pairs, start=1): self.tree.set(k, v) eq_(len(self.tree), i) for k, v in pairs: eq_(self.tree.get(k), v) random.shuffle(pairs) for i, (k, v) in enumerate(pairs, start=1): self.tree.pop(k) eq_(len(self.tree), len(pairs) - i) def test_overwrite_and_get_key(self): self.tree.set("a", "b") self.tree.set("a", "c") eq_(self.tree.get("a"), "c") def test_pop_non_existent_key(self): with assert_raises(KeyError): self.tree.pop("Not a key in the tree") def test_del_leaf_key(self): self.tree.set("b", "2") self.tree.pop("b") with assert_raises(KeyError): self.tree.get("b") def test_del_left_node_key(self): self.tree.set("b", "2") self.tree.set("a", "1") self.tree.pop("b") with assert_raises(KeyError): self.tree.get("b") self.tree.get("a") def test_del_right_node_key(self): self.tree.set("b", "2") self.tree.set("c", "3") self.tree.pop("b") with assert_raises(KeyError): self.tree.get("b") self.tree.get("c") def test_del_full_node_key(self): self.tree.set("b", "2") self.tree.set("a", "1") self.tree.set("c", "3") self.tree.pop("b") with assert_raises(KeyError): self.tree.get("b") self.tree.get("a") self.tree.get("c")