Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r63785:ffe6fdf3a875
Date: 2013-05-01 19:33 +0200
http://bitbucket.org/pypy/pypy/changeset/ffe6fdf3a875/

Log:    A version of zip() specialized for two arguments. It is more than
        four times faster (tested with lists of 10 items).

diff --git a/pypy/module/__builtin__/app_functional.py 
b/pypy/module/__builtin__/app_functional.py
--- a/pypy/module/__builtin__/app_functional.py
+++ b/pypy/module/__builtin__/app_functional.py
@@ -203,7 +203,29 @@
 Return a list of tuples, where each tuple contains the i-th element
 from each of the argument sequences.  The returned list is truncated
 in length to the length of the shortest argument sequence."""
-    if not sequences:
+    l = len(sequences)
+    if l == 2:
+        # This is functionally the same as the code below, but more
+        # efficient because it unrolls the loops over 'sequences'.
+        # Only for two arguments, which is the most common case.
+        seq0 = sequences[0]
+        seq1 = sequences[1]
+        iter0 = iter(seq0)
+        iter1 = iter(seq1)
+        hint = min(100000000,   # max 100M
+                   operator._length_hint(seq0, 0),
+                   operator._length_hint(seq1, 0))
+
+        with _ManagedNewlistHint(hint) as result:
+            while True:
+                try:
+                    item0 = next(iter0)
+                    item1 = next(iter1)
+                except StopIteration:
+                    return result
+                result.append((item0, item1))
+
+    if l == 0:
         return []
 
     # Gather the iterators and guess the result length (the min of the
diff --git a/pypy/module/__builtin__/test/test_zip.py 
b/pypy/module/__builtin__/test/test_zip.py
--- a/pypy/module/__builtin__/test/test_zip.py
+++ b/pypy/module/__builtin__/test/test_zip.py
@@ -13,6 +13,12 @@
     def test_one_list(self):
         assert zip([1, 2, 3]) == [(1,), (2,), (3,)]
 
+    def test_two_lists(self):
+        # uses a different code path
+        assert zip([1, 2, 3], [3, 4, 5]) == [(1, 3), (2, 4), (3, 5)]
+        assert zip([1, 2, 3], [3, 4]) == [(1, 3), (2, 4)]
+        assert zip([1, 2], [3, 4, 5]) == [(1, 3), (2, 4)]
+
     def test_three_lists_same_size(self):
         assert zip([1, 2, 3], [3, 4, 5], [6, 7, 8]) == (
                           [(1, 3, 6), (2, 4, 7), (3, 5, 8)])
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to