Sorry, PEP 3106 is not yet accepted. Also removed mutating operations
and added some clarifications.
This commit is contained in:
parent
d6a8f11a3a
commit
7c97ac0ea4
|
@ -78,7 +78,7 @@ Index by Category
|
|||
Accepted PEPs (accepted; may not be implemented yet)
|
||||
|
||||
SA 3102 Keyword-Only Arguments Talin
|
||||
SA 3106 Revamping dict.keys(), .values() and .items() GvR
|
||||
S 3106 Revamping dict.keys(), .values() and .items() GvR
|
||||
SA 3107 Function Annotations Winter, Lownds
|
||||
SA 3109 Raising Exceptions in Python 3000 Winter
|
||||
SA 3110 Catching Exceptions in Python 3000 Winter
|
||||
|
@ -449,7 +449,7 @@ Numerical Index
|
|||
S 3103 A Switch/Case Statement GvR
|
||||
S 3104 Access to Names in Outer Scopes Yee
|
||||
SF 3105 Make print a function Brandl
|
||||
SA 3106 Revamping dict.keys(), .values() and .items() GvR
|
||||
S 3106 Revamping dict.keys(), .values() and .items() GvR
|
||||
SA 3107 Function Annotations Winter, Lownds
|
||||
I 3108 Standard Library Reorganization Cannon
|
||||
SA 3109 Raising Exceptions in Python 3000 Winter
|
||||
|
|
83
pep-3106.txt
83
pep-3106.txt
|
@ -3,7 +3,7 @@ Title: Revamping dict.keys(), .values() and .items()
|
|||
Version: $Revision$
|
||||
Last-Modified: $Date$
|
||||
Author: Guido van Rossum
|
||||
Status: Accepted
|
||||
Status: Draft
|
||||
Type: Standards
|
||||
Content-Type: text/x-rst
|
||||
Created: 19-Dec-2006
|
||||
|
@ -14,11 +14,10 @@ Abstract
|
|||
========
|
||||
|
||||
This PEP proposes to change the .keys(), .values() and .items()
|
||||
methods of the built-in dict type to return a set-like or
|
||||
multiset-like (== bag-like) object whose contents are derived of the
|
||||
underlying dictionary rather than a list which is a copy of the keys,
|
||||
etc.; and to remove the .iterkeys(), .itervalues() and .iteritems()
|
||||
methods.
|
||||
methods of the built-in dict type to return a set-like or unordered
|
||||
container object whose contents are derived of the underlying
|
||||
dictionary rather than a list which is a copy of the keys, etc.; and
|
||||
to remove the .iterkeys(), .itervalues() and .iteritems() methods.
|
||||
|
||||
The approach is inspired by that taken in the Java Collections
|
||||
Framework [1]_.
|
||||
|
@ -72,25 +71,16 @@ d.iterkeys() (etc.) does in Python 2.x; but in most contexts we don't
|
|||
have to write the iter() call because it is implied by a for-loop.
|
||||
|
||||
The objects returned by the .keys() and .items() methods behave like
|
||||
sets with limited mutability; they allow removing elements, but not
|
||||
adding them. Removing an item from these sets removes it from the
|
||||
underlying dict. The object returned by the values() method behaves
|
||||
like a multiset (Java calls this a Collection). It does not allow
|
||||
removing elements, because a value might occur multiple times and the
|
||||
implementation wouldn't know which key to remove from the underlying
|
||||
dict. (The Java Collections Framework has a way around this by
|
||||
removing from an iterator, but I see no practical use case for that
|
||||
functionality.)
|
||||
sets. The object returned by the values() method behaves like a much
|
||||
simpler unordered collection; anything more would require too much
|
||||
implementation effort for the rare use case.
|
||||
|
||||
Because of the set behavior, it will be possible to check whether two
|
||||
dicts have the same keys by simply testing::
|
||||
|
||||
if a.keys() == b.keys(): ...
|
||||
|
||||
and similarly for values. (Two multisets are deemed equal if they
|
||||
have the same elements with the same cardinalities, e.g. the multiset
|
||||
{1, 2, 2} is equal to the multiset {2, 1, 2} but differs from the
|
||||
multiset {1, 2}.)
|
||||
and similarly for .items().
|
||||
|
||||
These operations are thread-safe only to the extent that using them in
|
||||
a thread-unsafe way may cause an exception but will not cause
|
||||
|
@ -145,26 +135,12 @@ I'm using pseudo-code to specify the semantics::
|
|||
for key in self.__d:
|
||||
yield key
|
||||
|
||||
def remove(self, key):
|
||||
del self.__d[key]
|
||||
|
||||
def discard(self, key):
|
||||
if key in self:
|
||||
self.remove(key)
|
||||
|
||||
def pop(self):
|
||||
return self.__d.popitem()[0]
|
||||
|
||||
def clear(self):
|
||||
self.__d.clear()
|
||||
|
||||
# The following operations should be implemented to be
|
||||
# compatible with sets; this can be done by exploiting
|
||||
# the above primitive operations:
|
||||
#
|
||||
# <, <=, ==, !=, >=, > (returning a bool)
|
||||
# &, |, ^, - (returning a new, real set object)
|
||||
# &=, -= (updating in place and returning self; but not |=, ^=)
|
||||
#
|
||||
# as well as their method counterparts (.union(), etc.).
|
||||
#
|
||||
|
@ -191,23 +167,6 @@ I'm using pseudo-code to specify the semantics::
|
|||
for key in self.__d:
|
||||
yield key, self.__d[key]
|
||||
|
||||
def remove(self, (key, value)):
|
||||
if (key, value) not in self:
|
||||
raise KeyError((key, value))
|
||||
del self.__d[key]
|
||||
|
||||
def discard(self, item):
|
||||
# Defined in terms of 'in' and .remove() so overriding
|
||||
# those will update discard appropriately.
|
||||
if item in self:
|
||||
self.remove(item)
|
||||
|
||||
def pop(self):
|
||||
return self.__d.popitem()
|
||||
|
||||
def clear(self):
|
||||
self.__d.clear()
|
||||
|
||||
# As well as the set operations mentioned for d_keys above.
|
||||
# However the specifications suggested there will not work if
|
||||
# the values aren't hashable. Fortunately, the operations can
|
||||
|
@ -288,11 +247,8 @@ I'm using pseudo-code to specify the semantics::
|
|||
# XXX Sometimes this could be optimized, but these are the
|
||||
# semantics: we can't depend on the values to be hashable
|
||||
# or comparable.
|
||||
o = list(other)
|
||||
for x in self:
|
||||
try:
|
||||
o.remove(x)
|
||||
except ValueError:
|
||||
if not o in other:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
@ -302,13 +258,21 @@ I'm using pseudo-code to specify the semantics::
|
|||
result = not result
|
||||
return result
|
||||
|
||||
Note that we don't implement .copy() -- the presence of a .copy()
|
||||
Notes:
|
||||
|
||||
The view objects are not directly mutable, but don't implement
|
||||
__hash__(); their value can change if the underlying dict is mutated.
|
||||
|
||||
The only requirements on the underlying dict are that it implements
|
||||
__getitem__(), __contains__(), __iter__(), and __len__(0.
|
||||
|
||||
We don't implement .copy() -- the presence of a .copy()
|
||||
method suggests that the copy has the same type as the original, but
|
||||
that's not feasible without copying the underlying dict. If you want
|
||||
a copy of a specific type, like list or set, you can just pass one
|
||||
of the above to the list() or set() constructor.
|
||||
|
||||
Also note that the specification implies that the order in which items
|
||||
The specification implies that the order in which items
|
||||
are returned by .keys(), .values() and .items() is the same (just as
|
||||
it was in Python 2.x), because the order is all derived from the dict
|
||||
iterator (which is presumably arbitrary but stable as long as a dict
|
||||
|
@ -325,7 +289,7 @@ set operations on keys and items without having to copy them should
|
|||
speak for itself.
|
||||
|
||||
I've left out the implementation of various set operations. These
|
||||
could still present surprises.
|
||||
could still present small surprises.
|
||||
|
||||
It would be okay if multiple calls to d.keys() (etc.) returned the
|
||||
same object, since the object's only state is the dict to which it
|
||||
|
@ -334,11 +298,6 @@ Should that be a weak reference or should the d_keys (etc.) object
|
|||
live forever once created? Strawman: probably not worth the extra
|
||||
slots in every dict.
|
||||
|
||||
Should d_values have mutating methods (pop(), clear())? Strawman: no.
|
||||
|
||||
Should d_values implement set operations (as defined for multisets).
|
||||
Strawman: no.
|
||||
|
||||
Should d_keys, d_values and d_items have a public instance variable or
|
||||
method through which one can retrieve the underlying dict? Strawman:
|
||||
yes (but what should it be called?).
|
||||
|
|
Loading…
Reference in New Issue