Playing with Dict - Can anyone see a way around this?

s713221 at student.gu.edu.au s713221 at student.gu.edu.au
Sat May 19 18:08:57 CEST 2001


Somebody mentioned in this group a couple of months ago, the posibility
of making [].keys, [].items and [].values directly scriptable, so you
could iterate over them either by calling them, or by treating them as
lists. I've taken their suggestion as far as I can go as an exercise in
curiosity, but have run into a little bit of a problem. I took their
suggestion of making keys, values and items, classes rather than
functions.

class MyDict:
	def __init__(self):
		self.dict = {}
		self.keys = self.__keys(self.dict)
		self.items = self.__items(self.dict)
		self.values = self.__values(self.dict)
	def __getitem__(self,item):
		return self.dict[item]
	def __setitem__(self,item,value):
		self.dict[item] = value
	def __getattr__(self,key):
		if key in ['keys','items','values']:
			return self.__dict__[key]
		else:
			return self.dict[key]
	def __repr__(self):
                return str(self.dict)
        def __delitem__(self,item):
                del self.dict[item]
        class __keys:
                def __init__(self,dict):
                        self.dict = dict
                def __repr__(self):
                        return str(self.dict.keys())
                def __call__(self):
                        return self.dict.keys()
                def __getitem__(self,item):
                        return self.dict.keys()[item]
        class __items:
                def __init__(self,dict):
                        self.dict = dict
                def __repr__(self):
                        return str(self.dict.items())
                def __call__(self):
                        return self.dict.items()
                def __getitem__(self,item):
                        return self.dict.items()[item]
        class __values:
                def __init__(self,dict):
                        self.dict = dict
                def __repr__(self):
                        return str(self.dict.values())
                def __call__(self):
                        return self.dict.values()
                def __getitem__(self,item):
                        return self.dict.values()[item]

Now this mostly works
>>> a = MyDict()
>>> for i in range(10):
	a[i] = i

>>> a
{9: 9, 8: 8, 7: 7, 6: 6, 5: 5, 4: 4, 3: 3, 2: 2, 1: 1, 0: 0}
>>> a.keys
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>> a.values
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>> a.items
[(9, 9), (8, 8), (7, 7), (6, 6), (5, 5), (4, 4), (3, 3), (2, 2), (1, 1),
(0, 0)]

And it's possible to iterate over a.items in the following ways:
>>> for i in a.keys:
	print i,

	
9 8 7 6 5 4 3 2 1 0
>>> for i in a.keys():
	print i,

	
9 8 7 6 5 4 3 2 1 0
>>> for i in a.items():
	print i,

	
(9, 9) (8, 8) (7, 7) (6, 6) (5, 5) (4, 4) (3, 3) (2, 2) (1, 1) (0, 0)

However, I've hit a rather interesting hiccup, due to i.keys returning
the class __keys, rather than a list of keys. Umm, it's explained better
in the example.

Now everything looks okay at first glance, due to some hacking on
__keys.__repr__
>>> b = a.keys
>>> b
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

But watch what happens when I iterate over a.keys and change the
dictionary in place.
>>> for i in a.keys:
	print i
	del a[i]

	
9
7
5
3
1
>>> a
{8: 8, 6: 6, 4: 4, 2: 2, 0: 0}

Whoops. Not what I wanted. And this invalidates my aim of having a.keys
and a.keys() acting the same way.
>>> for i in a.keys():
	print i
	del a[i]

	
9
8
7
6
5
4
3
2
1
0
>>> 

Anycase, can anyone see a way around this? This is mostly for curiosity,
but I'm damned curious at the moment.

Joal Heagney/AncientHart



More information about the Python-list mailing list