hash.py

30分プログラム、その21。
Hashの自前実装。Python風に言うならディクショナリ。

>>> import myhash
>>> myhash = myhash.MyHash()

>>> myhash['spam'] = 1
>>> myhash['egg'] = 2
>>> myhash['ham'] = 0

>>> myhash['spam']
1
>>> myhash['egg']
2
>>> myhash['spam']
1
>>> myhash['ham']
0

>>> for (k,v) in myhash:
...     print k,v
...
egg 2
spam 1
ham 0

>>> len(myhash)
3
class MyHash:
    def __init__(self,size=10):
	self.size = size
	self.list = [None]*size
 
    def __getitem__(self,key):
	index = hash(key) % self.size
	if self.list[index] == None:
	    return None
	else:
	    for (k,v) in self.list[index]:
		if key == k:
		    return v
	    return None
 
    def __setitem__(self,key,value):
	index = hash(key) % self.size
	if self.list[index] == None:
	    self.list[index] = []
	self.list[index].append((key,value))
 
    def __delitem__(self,key):
	index = hash(key) % self.size
	if self.list[index] != None:
	    for i in xrange(0,len(self.list[index])):
		if key == self.list[index][i][0]:
		    del self.list[index][i]
 
    def __iter__(self):
	for list in self.list:
	    if list != None:
		for pair in list:
		    yield pair
	raise StopIteration
 
    def __len__(self):
	sum = 0
	for list in self.list:
	    if list != None:
		sum += len(list)
	return sum
 
if __name__ == '__main__':
    my_hash = MyHash()
    my_hash['spam'] = 2
    my_hash['ham'] = 1
    my_hash['eggs'] = 3
    print my_hash['spam']
    print my_hash['ham']
    print my_hash['eggs']
 
    for (key,value) in my_hash:
	print "key:",key
	print "value:",value
 
	print len(my_hash)
  • 始め、self.list = [[]] * sizeとやっていた。これだと浅いコピーと似た問題が起きた
  • __iter__とyieldは相性いいね
  • __iter__と__len__の共通部分をまとめようとしたけど、うまくいかなかった。yieldのせいかな