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)
|
Accepted PEPs (accepted; may not be implemented yet)
|
||||||
|
|
||||||
SA 3102 Keyword-Only Arguments Talin
|
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 3107 Function Annotations Winter, Lownds
|
||||||
SA 3109 Raising Exceptions in Python 3000 Winter
|
SA 3109 Raising Exceptions in Python 3000 Winter
|
||||||
SA 3110 Catching 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 3103 A Switch/Case Statement GvR
|
||||||
S 3104 Access to Names in Outer Scopes Yee
|
S 3104 Access to Names in Outer Scopes Yee
|
||||||
SF 3105 Make print a function Brandl
|
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
|
SA 3107 Function Annotations Winter, Lownds
|
||||||
I 3108 Standard Library Reorganization Cannon
|
I 3108 Standard Library Reorganization Cannon
|
||||||
SA 3109 Raising Exceptions in Python 3000 Winter
|
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$
|
Version: $Revision$
|
||||||
Last-Modified: $Date$
|
Last-Modified: $Date$
|
||||||
Author: Guido van Rossum
|
Author: Guido van Rossum
|
||||||
Status: Accepted
|
Status: Draft
|
||||||
Type: Standards
|
Type: Standards
|
||||||
Content-Type: text/x-rst
|
Content-Type: text/x-rst
|
||||||
Created: 19-Dec-2006
|
Created: 19-Dec-2006
|
||||||
|
@ -14,11 +14,10 @@ Abstract
|
||||||
========
|
========
|
||||||
|
|
||||||
This PEP proposes to change the .keys(), .values() and .items()
|
This PEP proposes to change the .keys(), .values() and .items()
|
||||||
methods of the built-in dict type to return a set-like or
|
methods of the built-in dict type to return a set-like or unordered
|
||||||
multiset-like (== bag-like) object whose contents are derived of the
|
container object whose contents are derived of the underlying
|
||||||
underlying dictionary rather than a list which is a copy of the keys,
|
dictionary rather than a list which is a copy of the keys, etc.; and
|
||||||
etc.; and to remove the .iterkeys(), .itervalues() and .iteritems()
|
to remove the .iterkeys(), .itervalues() and .iteritems() methods.
|
||||||
methods.
|
|
||||||
|
|
||||||
The approach is inspired by that taken in the Java Collections
|
The approach is inspired by that taken in the Java Collections
|
||||||
Framework [1]_.
|
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.
|
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
|
The objects returned by the .keys() and .items() methods behave like
|
||||||
sets with limited mutability; they allow removing elements, but not
|
sets. The object returned by the values() method behaves like a much
|
||||||
adding them. Removing an item from these sets removes it from the
|
simpler unordered collection; anything more would require too much
|
||||||
underlying dict. The object returned by the values() method behaves
|
implementation effort for the rare use case.
|
||||||
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.)
|
|
||||||
|
|
||||||
Because of the set behavior, it will be possible to check whether two
|
Because of the set behavior, it will be possible to check whether two
|
||||||
dicts have the same keys by simply testing::
|
dicts have the same keys by simply testing::
|
||||||
|
|
||||||
if a.keys() == b.keys(): ...
|
if a.keys() == b.keys(): ...
|
||||||
|
|
||||||
and similarly for values. (Two multisets are deemed equal if they
|
and similarly for .items().
|
||||||
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}.)
|
|
||||||
|
|
||||||
These operations are thread-safe only to the extent that using them in
|
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
|
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:
|
for key in self.__d:
|
||||||
yield key
|
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
|
# The following operations should be implemented to be
|
||||||
# compatible with sets; this can be done by exploiting
|
# compatible with sets; this can be done by exploiting
|
||||||
# the above primitive operations:
|
# the above primitive operations:
|
||||||
#
|
#
|
||||||
# <, <=, ==, !=, >=, > (returning a bool)
|
# <, <=, ==, !=, >=, > (returning a bool)
|
||||||
# &, |, ^, - (returning a new, real set object)
|
# &, |, ^, - (returning a new, real set object)
|
||||||
# &=, -= (updating in place and returning self; but not |=, ^=)
|
|
||||||
#
|
#
|
||||||
# as well as their method counterparts (.union(), etc.).
|
# 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:
|
for key in self.__d:
|
||||||
yield key, self.__d[key]
|
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.
|
# As well as the set operations mentioned for d_keys above.
|
||||||
# However the specifications suggested there will not work if
|
# However the specifications suggested there will not work if
|
||||||
# the values aren't hashable. Fortunately, the operations can
|
# 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
|
# XXX Sometimes this could be optimized, but these are the
|
||||||
# semantics: we can't depend on the values to be hashable
|
# semantics: we can't depend on the values to be hashable
|
||||||
# or comparable.
|
# or comparable.
|
||||||
o = list(other)
|
|
||||||
for x in self:
|
for x in self:
|
||||||
try:
|
if not o in other:
|
||||||
o.remove(x)
|
|
||||||
except ValueError:
|
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -302,13 +258,21 @@ I'm using pseudo-code to specify the semantics::
|
||||||
result = not result
|
result = not result
|
||||||
return 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
|
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
|
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
|
a copy of a specific type, like list or set, you can just pass one
|
||||||
of the above to the list() or set() constructor.
|
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
|
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
|
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
|
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.
|
speak for itself.
|
||||||
|
|
||||||
I've left out the implementation of various set operations. These
|
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
|
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
|
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
|
live forever once created? Strawman: probably not worth the extra
|
||||||
slots in every dict.
|
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
|
Should d_keys, d_values and d_items have a public instance variable or
|
||||||
method through which one can retrieve the underlying dict? Strawman:
|
method through which one can retrieve the underlying dict? Strawman:
|
||||||
yes (but what should it be called?).
|
yes (but what should it be called?).
|
||||||
|
|
Loading…
Reference in New Issue