[Python-3000] Iterators for dict keys, values, and items == annoying :)
Ian Bicking
ianb at colorstudy.com
Fri Mar 31 00:50:33 CEST 2006
Guido van Rossum wrote:
> On 3/30/06, Nick Coghlan <ncoghlan at gmail.com> wrote:
>
>>Adam DePrince wrote:
>>
>>>There seemed to be a concensus in the community on the size of the view
>>>proposal, and I'm reimplementing the PEP to reflect that. But what I
>>>can't resolve is the other anciliary issue: "To list or iter." I'm not
>>>yet ready to resolve that issue. The views don't resolve it either, and
>>>by their nature are biased towards the iter approach. They provide
>>>__iter__ because its light weight to do, but there is no way a light
>>>weight view can provide you with ordering information from an unordered
>>>datastore. Now, as a means of resolving this conflict, I'm open to the
>>>notion of a view implementing both __iter__ and an explicit .list method
>>>to avoid any extra overhead in generating a list from an iter instead of
>>>directly from the dict as we do now.
>>
>>Umm, the whole point of the views discussion is the realisation that "list or
>>iterator" is a false dichotomy. The correct answer is "new iterable that looks
>>like a container in its own right, but is really just a view of the original".
>>
>>As far as the value-based comparison goes, yes, in reality the view will need
>>to have greater knowledge of the underlying container than in my sample
>>classes in order to be sure of getting a consistent ordering from the
>>underlying objects.
>>
>>As Python's own set and dict show, however, unordered collections can be
>>legitimately compared by value.
>
>
> Boy. I definitely need to make time to read this discussion and the PEP.
>
> Java does it this way and I think we can do the same thing:
>
> keys() and items() return views that behave like sets; values()
> returns a view that behaves like a collection (aka multiset or bag).
> Neither behaves like a list, which means that the order is unspecified
> (even though of course iteration reveals an order, there's nothing
> that says the order needs to remain the same).
>
> We need to be careful with copying Java's definition of equality
> though -- for sets, any two objects implementing the Set interface
> must compare equal iff they are contained in each other (the standard
> mathematical definition), and for collections they give two options:
> reference equality (i.e. they are the same object) or some other
> symmetric equality that however cannot equal a set or list containing
> the same values (sets can only be equal to other sets, and lists only
> to other lists).
>
> That's quite different from Python's equality definitions, which don't
> take interfaces into account but only concrete types. Adam correctly
> pointed out the bugs in Nick's __eq__ implementation (depending on the
> order), but this is easy enough to fix (though expensive to execute
> since it would require casting keys and items to sets, and doing some
> kind of multiset comparison for values).
>
> But that doesn't answer the question about the following code
>
> a = {1: "one", 2: "two"}
> b = set(a.keys())
> c = a.keys() # assuming keys() returns a "set view"
> print b == c
>
> Here b is a concrete set object; c is a set view of a's keys. These
> are presumably different types (since the concrete set contains its
> own hash table while the set view just contains a reference to the
> dict a). So Nick's definition of __eq__ makes them unequal. However
> Java would consider them equal (since both implement the set
> interface, and both contain the same elements).
>
> We could say that sets and set-like objects should be comparable, but
> that requires us to define exactly what we consider set-like; this is
> difficult in a world of duck typing. It would also presumably require
> us (out of fairness if anything) to allow sequences to be compared for
> equality, so [1,2,3] and (1,2,3) would henceforth compare equal. And
> similar for mappings. All with the same problems.
Set-like is anything that subclasses baseset? But maybe there's a
deeper answer somewhere, as base* types seem a bit kludgy. A
collection-specific protocol for testing equality would be reasonable.
It doesn't break duck typing, just adds a bit more to the interfaces of
collections than purely a bunch of disparate methods.
A generic view protocol could maybe handle it too, so you'd ask an
object to give a set-like view of itself when comparing that object to a
set, and then test that. And the object could return itself, if it
already implemented a set-like view. Or return None, meaning no such
view was possible. At which point it sounds just like adaptation.
--
Ian Bicking / ianb at colorstudy.com / http://blog.ianbicking.org
More information about the Python-3000
mailing list