[Python-3000] Iterators for dict keys, values, and items == annoying :)
Nick Coghlan
ncoghlan at gmail.com
Thu Mar 30 12:23:56 CEST 2006
Robert Brewer wrote:
> Nick Coghlan wrote:
>> There are three big use cases:
>>
>> dict.keys
>> dict.values
>> dict.items
>>
>> Currently these all return lists, which may be expensive in
>> terms of copying. They all have iter* variants which while
>> memory efficient, are far less convenient to work with.
>
> I'm still wondering what "far less convenient" means. Is it simply the 4
> extra key presses? I find the iter* variants to be a great solution.
An iterator has some serious limitations as a view of a container:
1. Can only iterate once
2. Can't check number of items
3. Truth value testing doesn't work
4. Containment tests don't work
5. String representation is well-nigh useless
6. Value-based comparison doesn't work
The source object supports all of these things, but the iterator doesn't. This
is why iteritems and friends are poor substitutes for their list based
equivalents in many situations.
Consider, however, the following view-based approach:
from itertools import izip
class _containerview(object):
"""Default behaviour for container views"""
def __init__(self, container):
self.container = container
def __len__(self):
return len(self.container)
def __iter__(self):
return iter(self.container)
def __contains__(self, val):
return val in self.container
def __eq__(self, other):
# Check they're the same type
if type(self) != type(other):
return False
# Check they're the same size
if len(self) != len(other):
return False
# Check they have the same elements
for this, that in izip(self, other):
if this != that:
return False
return True
def __ne__(self, other):
return not self.__eq__(other)
def __str__(self):
type_name = type(self).__name__
details = ", ".join(self)
return "%s([%s])" % (type_name, details)
class keyview(_containerview):
"""Convenient view of dictionary keys"""
# The default behaviour is always right
class valueview(_containerview):
"""Convenient view of dictionary values"""
def __iter__(self):
return self.container.itervalues()
def __contains__(self, val):
for item in self:
if item == val:
return True
return False
class itemview(_containerview):
"""Convenient view of dictionary items"""
def __iter__(self):
return self.container.iteritems()
def __contains__(self, item):
if not isinstance(item, tuple):
return False
if len(item) != 2:
return False
key, val = item
try:
stored_val = self.container[key]
except AttributeError:
return False
return stored_val == val
Cheers,
Nick.
--
Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia
---------------------------------------------------------------
http://www.boredomandlaziness.org
More information about the Python-3000
mailing list