Author: Lukas Diekmann <[email protected]>
Branch: list-strategies
Changeset: r47547:89afe67415a7
Date: 2011-09-13 16:34 +0200
http://bitbucket.org/pypy/pypy/changeset/89afe67415a7/
Log: deferred contains to strategies
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
@@ -107,6 +107,9 @@
# XXX what is this used for?
self.strategy.copy_into(self, other)
+ def contains(self, w_obj):
+ return self.strategy.contains(self, w_obj)
+
def append(w_list, w_item):
w_list.strategy.append(w_list, w_item)
@@ -175,6 +178,9 @@
def copy_into(self, w_list, w_other):
raise NotImplementedError
+ def contains(self, w_list, w_obj):
+ raise NotImplementedError
+
def length(self, w_list):
raise NotImplementedError
@@ -248,6 +254,9 @@
def copy_into(self, w_list, w_other):
pass
+ def contains(self, w_list, w_obj):
+ return self.space.w_False
+
def length(self, w_list):
return 0
@@ -335,6 +344,17 @@
w_other.strategy = self
w_other.lstorage = w_list.lstorage
+ def contains(self, w_list, w_obj):
+ if is_W_IntObject(w_obj):
+ start, step, length = self.unerase(w_list.lstorage)
+ obj = self.unwrap(w_obj)
+ i = start
+ while i < start + step * length:
+ if i == obj:
+ return self.space.w_True
+ i += step
+ return self.space.w_False
+
def length(self, w_list):
return self.unerase(w_list.lstorage)[2]
@@ -512,6 +532,16 @@
items = self.unerase(w_list.lstorage)[:]
w_other.lstorage = self.erase(items)
+ def contains(self, w_list, w_obj):
+ if self.is_correct_type(w_obj):
+ obj = self.unwrap(w_obj)
+ l = self.unerase(w_list.lstorage)
+ #XXX why do I need to check mutation for eq_w?
+ for i in l:
+ if i == obj:
+ return self.space.w_True
+ return self.space.w_False
+
def length(self, w_list):
return len(self.unerase(w_list.lstorage))
@@ -918,15 +948,7 @@
def contains__List_ANY(space, w_list, w_obj):
# needs to be safe against eq_w() mutating the w_list behind our back
- # XXX we want to defer that to the list strategy, because it would be a lot
- # more efficient to not call eq_w on ints. contains is used rather often
in code like:
- # if i in [1, 2, 3]: ...
- i = 0
- while i < w_list.length(): # intentionally always calling len!
- if space.eq_w(w_list.getitem(i), w_obj):
- return space.w_True
- i += 1
- return space.w_False
+ return w_list.contains(w_obj)
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
@@ -353,6 +353,39 @@
l2 = [1, "2", "a", "a"]
assert sorted(l1) == sorted(l2)
+ def test_contains(self):
+ l = []
+ assert not l.__contains__(2)
+
+ l = [1,2,3]
+ assert l.__contains__(2)
+ assert not l.__contains__("2")
+
+ l = ["1","2","3"]
+ assert l.__contains__("2")
+ assert not l.__contains__(2)
+
+ l = range(4)
+ assert l.__contains__(2)
+ assert not l.__contains__("2")
+
+ l = [1,2,"3"]
+ assert l.__contains__(2)
+ assert not l.__contains__("2")
+
+ l = range(2, 20, 3) # = [2, 5, 8, 11, 14, 17]
+ assert l.__contains__(2)
+ assert l.__contains__(5)
+ assert l.__contains__(8)
+ assert l.__contains__(11)
+ assert l.__contains__(14)
+ assert l.__contains__(17)
+ assert not l.__contains__(3)
+ assert not l.__contains__(4)
+ assert not l.__contains__(7)
+ assert not l.__contains__(13)
+ assert not l.__contains__(20)
+
def test_call_list(self):
assert list('') == []
assert list('abc') == ['a', 'b', 'c']
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit