Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r90065:6b030e17ad91 Date: 2017-02-12 09:58 +0100 http://bitbucket.org/pypy/pypy/changeset/6b030e17ad91/
Log: In the common strategies, implement a version of pop() doing only one dict lookup 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 @@ -365,6 +365,13 @@ corresponding value\nIf key is not found, d is returned if given, otherwise KeyError is raised """ + strategy = self.get_strategy() + if strategy.has_pop: + try: + return strategy.pop(self, w_key, w_default) + except KeyError: + raise space.raise_key_error(w_key) + # fall-back w_item = self.getitem(w_key) if w_item is None: if w_default is not None: @@ -616,6 +623,7 @@ has_iterreversed = False has_move_to_end = False + has_pop = False # ^^^ no default implementation available for these methods def rev_update1_dict_dict(self, w_dict, w_updatedict): @@ -890,6 +898,9 @@ if hasattr(dictimpl, 'move_to_end'): dictimpl.has_move_to_end = True + if hasattr(dictimpl, 'pop'): + dictimpl.has_pop = True + @jit.look_inside_iff(lambda self, w_dict, w_updatedict: w_dict_unrolling_heuristic(w_dict)) def rev_update1_dict_dict(self, w_dict, w_updatedict): @@ -1028,6 +1039,21 @@ key, value = self.unerase(w_dict.dstorage).popitem() return (self.wrap(key), value) + def pop(self, w_dict, w_key, w_default): + space = self.space + if self.is_correct_type(w_key): + key = self.unwrap(w_key) + d = self.unerase(w_dict.dstorage) + if w_default is None: + return d.pop(key) + else: + return d.pop(key, w_default) + elif self._never_equal_to(space.type(w_key)): + raise KeyError + else: + self.switch_to_object_strategy(w_dict) + return w_dict.get_strategy().pop(w_dict, w_key, w_default) + def clear(self, w_dict): self.unerase(w_dict.dstorage).clear() 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 @@ -663,6 +663,18 @@ else: assert False, 'Expected KeyError' + def test_pop_switching_strategy(self): + class Foo: + def __hash__(self): + return hash("a") + def __eq__(self, other): + return other == "a" + d = {"a": 42} + x = d.pop(Foo()) + assert x == 42 and len(d) == 0 + d = {"b": 43} + raises(KeyError, d.pop, Foo()) + def test_no_len_on_dict_iter(self): iterable = {1: 2, 3: 4} raises(TypeError, len, iter(iterable)) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit