Author: Lukas Diekmann <[email protected]>
Branch: set-strategies
Changeset: r49163:a9c59d68f3ac
Date: 2011-05-18 15:42 +0200
http://bitbucket.org/pypy/pypy/changeset/a9c59d68f3ac/

Log:    added intelligent way to treat the different strategies in
        W_SetObject.difference

diff --git a/pypy/objspace/std/setobject.py b/pypy/objspace/std/setobject.py
--- a/pypy/objspace/std/setobject.py
+++ b/pypy/objspace/std/setobject.py
@@ -391,34 +391,50 @@
         return True
 
     def difference(self, w_set, w_other):
-        #XXX return clone if other is Empty
-        result = w_set._newobj(self.space, None)
         if not isinstance(w_other, W_BaseSetObject):
             w_other = w_set._newobj(self.space, w_other)
-        # lookup is faster when w_other is set
-        for w_key in w_set.getkeys():
-            if not w_other.has_key(w_key):
-                result.add(w_key)
+
+        if w_other.strategy is self.space.fromcache(ObjectSetStrategy):
+            return self.difference_wrapped(w_set, w_other)
+
+        if w_set.strategy is not w_other.strategy:
+            return w_set.copy()
+
+        return self.difference_unwrapped(w_set, w_other)
+
+    def difference_wrapped(self, w_set, w_other):
+        result = w_set._newobj(self.space, None)
+        w_iter = self.space.iter(w_set)
+        while True:
+            try:
+                w_item = self.space.next(w_iter)
+                if not w_other.has_key(w_key):
+                    result.add(w_key)
+            except OperationError, e:
+                if not e.match(self.space, self.space.w_StopIteration):
+                    raise
+                return
+        return result
+
+    def difference_unwrapped(self, w_set, w_other):
+        if not isinstance(w_other, W_BaseSetObject):
+            w_other = w_set._newobj(self.space, w_other)
+        iterator = self.cast_from_void_star(w_set.sstorage).iterkeys()
+        other_dict = self.cast_from_void_star(w_other.sstorage)
+        result_dict = self.get_empty_dict()
+        for key in iterator:
+            if key not in other_dict:
+                result_dict[key] = None
+        result = w_set._newobj(self.space, None)
+        result.strategy = self
+        result.sstorage = self.cast_to_void_star(result_dict)
         return result
 
     def difference_update(self, w_set, w_other):
-        if w_other.strategy is EmptySetStrategy:
-            return
-        if w_set is w_other:
-            w_set.clear()     # for the case 'a.difference_update(a)'
-        else:
-            w_iter = self.space.iter(w_other)
-            while True:
-                try:
-                    w_item = self.space.next(w_iter)
-                    try:
-                        self.delitem(w_set, w_item)
-                    except KeyError:
-                        pass
-                except OperationError, e:
-                    if not e.match(self.space, self.space.w_StopIteration):
-                        raise
-                    return
+        #XXX this way we unnecessarily create a new set
+        result = self.difference(w_set, w_other)
+        w_set.strategy = result.strategy
+        w_set.sstorage = result.sstorage
 
     def symmetric_difference(self, w_set, w_other):
         #XXX no wrapping when strategies are equal
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to