Author: Carl Friedrich Bolz <[email protected]>
Branch: remove-list-smm
Changeset: r62545:7806a754f7d9
Date: 2013-03-20 12:06 +0100
http://bitbucket.org/pypy/pypy/changeset/7806a754f7d9/
Log: share code between find, contains and remove
diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -209,10 +209,10 @@
strategy and storage according to the other W_List"""
self.strategy.copy_into(self, other)
- def contains(self, w_obj):
- """Returns unwrapped boolean, saying wether w_obj exists
- in the list."""
- return self.strategy.contains(self, w_obj)
+
+ def find(self, w_item, start=0, end=maxint):
+ """Find w_item in list[start:end]. If not found, raise ValueError"""
+ return self.strategy.find(self, w_item, start, end)
def append(self, w_item):
'L.append(object) -- append object to end'
@@ -378,15 +378,14 @@
def descr_remove(self, space, w_value):
'L.remove(value) -- remove first occurrence of value'
# needs to be safe against eq_w() mutating the w_list behind our back
- i = 0
- while i < self.length():
- if space.eq_w(self.getitem(i), w_value):
- if i < self.length(): # if this is wrong the list was changed
- self.pop(i)
- return space.w_None
- i += 1
- raise OperationError(space.w_ValueError,
- space.wrap("list.remove(x): x not in list"))
+ try:
+ i = self.find(w_value, 0, maxint)
+ except ValueError:
+ raise OperationError(space.w_ValueError,
+ space.wrap("list.remove(x): x not in list"))
+ if i < self.length(): # otherwise list was mutated
+ self.pop(i)
+ return space.w_None
@unwrap_spec(w_start=WrappedDefault(0), w_stop=WrappedDefault(maxint))
def descr_index(self, space, w_value, w_start, w_stop):
@@ -396,12 +395,12 @@
size = self.length()
i, stop = slicetype.unwrap_start_stop(
space, size, w_start, w_stop, True)
- while i < stop and i < self.length():
- if space.eq_w(self.getitem(i), w_value):
- return space.wrap(i)
- i += 1
- raise OperationError(space.w_ValueError,
- space.wrap("list.index(x): x not in list"))
+ try:
+ i = self.find(w_value, i, stop)
+ except ValueError:
+ raise OperationError(space.w_ValueError,
+ space.wrap("list.index(x): x not in list"))
+ return space.wrap(i)
@unwrap_spec(reverse=bool)
def descr_sort(self, space, w_cmp=None, w_key=None, reverse=False):
@@ -498,14 +497,15 @@
def _resize_hint(self, w_list, hint):
raise NotImplementedError
- def contains(self, w_list, w_obj):
- # needs to be safe against eq_w() mutating the w_list behind our back
- i = 0
- while i < w_list.length(): # intentionally always calling len!
- if self.space.eq_w(w_list.getitem(i), w_obj):
- return True
+ def find(self, w_list, w_item, start, stop):
+ space = self.space
+ i = start
+ # needs to be safe against eq_w mutating stuff
+ while i < stop and i < w_list.length():
+ if space.eq_w(w_list.getitem(i), w_item):
+ return i
i += 1
- return False
+ raise ValueError
def length(self, w_list):
raise NotImplementedError
@@ -631,8 +631,8 @@
if hint:
w_list.strategy = SizeListStrategy(self.space, hint)
- def contains(self, w_list, w_obj):
- return False
+ def find(self, w_list, w_item, start, stop):
+ raise ValueError
def length(self, w_list):
return 0
@@ -786,17 +786,19 @@
w_other.strategy = self
w_other.lstorage = w_list.lstorage
- def contains(self, w_list, w_obj):
+ def find(self, w_list, w_obj, startindex, stopindex):
if is_W_IntObject(w_obj):
+ obj = self.unwrap(w_obj)
start, step, length = self.unerase(w_list.lstorage)
- obj = self.unwrap(w_obj)
- if step > 0 and start <= obj <= start + (length - 1) * step and
(start - obj) % step == 0:
- return True
- elif step < 0 and start + (length - 1) * step <= obj <= start and
(start - obj) % step == 0:
- return True
+ if ((step > 0 and start <= obj <= start + (length - 1) * step and
(start - obj) % step == 0) or
+ (step < 0 and start + (length - 1) * step <= obj <= start and
(start - obj) % step == 0)):
+ index = (obj - start) // step
else:
- return False
- return ListStrategy.contains(self, w_list, w_obj)
+ raise ValueError
+ if startindex <= index < stopindex:
+ return index
+ raise ValueError
+ return ListStrategy.find(self, w_list, w_obj, startindex, stopindex)
def length(self, w_list):
return self.unerase(w_list.lstorage)[2]
@@ -972,17 +974,18 @@
items = self.unerase(w_list.lstorage)[:]
w_other.lstorage = self.erase(items)
- def contains(self, w_list, w_obj):
+ def find(self, w_list, w_obj, start, stop):
if self.is_correct_type(w_obj):
- return self._safe_contains(w_list, self.unwrap(w_obj))
- return ListStrategy.contains(self, w_list, w_obj)
+ return self._safe_find(w_list, self.unwrap(w_obj), start, stop)
+ return ListStrategy.find(self, w_list, w_obj, start, stop)
- def _safe_contains(self, w_list, obj):
+ def _safe_find(self, w_list, obj, start, stop):
l = self.unerase(w_list.lstorage)
- for i in l:
- if i == obj:
- return True
- return False
+ for i in range(start, min(stop, len(l))):
+ val = l[i]
+ if val == obj:
+ return i
+ raise ValueError
def length(self, w_list):
return len(self.unerase(w_list.lstorage))
@@ -1224,8 +1227,8 @@
def clear(self, w_list):
w_list.lstorage = self.erase([])
- def contains(self, w_list, w_obj):
- return ListStrategy.contains(self, w_list, w_obj)
+ def find(self, w_list, w_obj, start, stop):
+ return ListStrategy.find(self, w_list, w_obj, start, stop)
def getitems(self, w_list):
return self.unerase(w_list.lstorage)
@@ -1408,7 +1411,11 @@
w_list.deleteslice(start, 1, stop-start)
def contains__List_ANY(space, w_list, w_obj):
- return space.wrap(w_list.contains(w_obj))
+ try:
+ w_list.find(w_obj)
+ return space.w_True
+ except ValueError:
+ return space.w_False
def iter__List(space, w_list):
from pypy.objspace.std import iterobject
diff --git a/pypy/objspace/std/test/test_listobject.py
b/pypy/objspace/std/test/test_listobject.py
--- a/pypy/objspace/std/test/test_listobject.py
+++ b/pypy/objspace/std/test/test_listobject.py
@@ -1,4 +1,5 @@
# coding: iso-8859-15
+import py
import random
from pypy.objspace.std.listobject import W_ListObject, SizeListStrategy,\
IntegerListStrategy, ObjectListStrategy
@@ -406,6 +407,19 @@
assert isinstance(w_lst.strategy, SizeListStrategy)
assert w_lst.strategy.sizehint == 13
+ def test_find_fast_on_intlist(self, monkeypatch):
+ monkeypatch.setattr(self.space, "eq_w", None)
+ w = self.space.wrap
+ intlist = W_ListObject(self.space,
[w(1),w(2),w(3),w(4),w(5),w(6),w(7)])
+ res = intlist.find(w(4), 0, 7)
+ assert res == 3
+ res = intlist.find(w(4), 0, 100)
+ assert res == 3
+ with py.test.raises(ValueError):
+ intlist.find(w(4), 4, 7)
+ with py.test.raises(ValueError):
+ intlist.find(w(4), 0, 2)
+
class AppTestW_ListObject(object):
def setup_class(cls):
import sys
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit