[pypy-commit] pypy default: Add a __contains__ method on dict.viewkeys() and dict.viewitems().
arigo
pypy.commits at gmail.com
Mon Feb 20 04:44:08 EST 2017
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r90219:d9ee4fe1cd44
Date: 2017-02-20 10:43 +0100
http://bitbucket.org/pypy/pypy/changeset/d9ee4fe1cd44/
Log: Add a __contains__ method on dict.viewkeys() and dict.viewitems().
Without it, it would walk the list, which is the wrong complexity
diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py
--- a/pypy/objspace/std/dictmultiobject.py
+++ b/pypy/objspace/std/dictmultiobject.py
@@ -1585,9 +1585,25 @@
def descr_iter(self, space):
return W_DictMultiIterItemsObject(space, self.w_dict.iteritems())
+ def descr_contains(self, space, w_item):
+ if not space.isinstance_w(w_item, space.w_tuple):
+ return space.w_False
+ try:
+ w_key, w_value = space.fixedview_unroll(w_item, 2)
+ w_found = self.w_dict.getitem(w_key)
+ except OperationError as e:
+ if e.async(space):
+ raise
+ w_found = None
+ if w_found is None:
+ return space.w_False
+ return space.eq(w_value, w_found)
+
class W_DictViewKeysObject(W_DictViewObject, SetLikeDictView):
def descr_iter(self, space):
return W_DictMultiIterKeysObject(space, self.w_dict.iterkeys())
+ def descr_contains(self, space, w_key):
+ return self.w_dict.descr_contains(space, w_key)
class W_DictViewValuesObject(W_DictViewObject):
def descr_iter(self, space):
@@ -1598,6 +1614,7 @@
__repr__ = interp2app(W_DictViewItemsObject.descr_repr),
__len__ = interp2app(W_DictViewItemsObject.descr_len),
__iter__ = interp2app(W_DictViewItemsObject.descr_iter),
+ __contains__ = interp2app(W_DictViewItemsObject.descr_contains),
__eq__ = interp2app(W_DictViewItemsObject.descr_eq),
__ne__ = interp2app(W_DictViewItemsObject.descr_ne),
@@ -1621,6 +1638,7 @@
__repr__ = interp2app(W_DictViewKeysObject.descr_repr),
__len__ = interp2app(W_DictViewKeysObject.descr_len),
__iter__ = interp2app(W_DictViewKeysObject.descr_iter),
+ __contains__ = interp2app(W_DictViewKeysObject.descr_contains),
__eq__ = interp2app(W_DictViewKeysObject.descr_eq),
__ne__ = interp2app(W_DictViewKeysObject.descr_ne),
diff --git a/pypy/objspace/std/test/test_dictmultiobject.py b/pypy/objspace/std/test/test_dictmultiobject.py
--- a/pypy/objspace/std/test/test_dictmultiobject.py
+++ b/pypy/objspace/std/test/test_dictmultiobject.py
@@ -806,6 +806,8 @@
assert "a" in keys
assert 10 not in keys
assert "Z" not in keys
+ raises(TypeError, "[] in keys") # [] is unhashable
+ raises(TypeError, keys.__contains__, [])
assert d.viewkeys() == d.viewkeys()
e = {1: 11, "a": "def"}
assert d.viewkeys() == e.viewkeys()
@@ -831,6 +833,8 @@
assert () not in items
assert (1,) not in items
assert (1, 2, 3) not in items
+ assert ([], []) not in items # [] is unhashable, but no TypeError
+ assert not items.__contains__(([], []))
assert d.viewitems() == d.viewitems()
e = d.copy()
assert d.viewitems() == e.viewitems()
More information about the pypy-commit
mailing list