Move itertools izip() code to builtins as zip(). Complete the renaming.

This commit is contained in:
Raymond Hettinger 2008-03-13 02:09:15 +00:00
parent c5a2eb949c
commit 736c0ab428
11 changed files with 281 additions and 476 deletions

View File

@ -7,7 +7,6 @@ extern "C" {
PyAPI_DATA(PyTypeObject) PySeqIter_Type;
PyAPI_DATA(PyTypeObject) PyCallIter_Type;
PyAPI_DATA(PyTypeObject) PyZipIter_Type;
PyAPI_DATA(PyTypeObject) PyCmpWrapper_Type;
#define PySeqIter_Check(op) (Py_TYPE(op) == &PySeqIter_Type)
@ -19,8 +18,6 @@ PyAPI_FUNC(PyObject *) PySeqIter_New(PyObject *);
PyAPI_FUNC(PyObject *) PyCallIter_New(PyObject *, PyObject *);
PyObject* _PyZip_CreateIter(PyObject* args);
#ifdef __cplusplus
}
#endif

View File

@ -12,7 +12,7 @@ Functions:
import os
import stat
import warnings
from itertools import filterfalse, izip
from itertools import filterfalse
__all__ = ["cmp","dircmp","cmpfiles"]
@ -130,8 +130,8 @@ class dircmp:
self.right_list.sort()
def phase1(self): # Compute common names
a = dict(izip(map(os.path.normcase, self.left_list), self.left_list))
b = dict(izip(map(os.path.normcase, self.right_list), self.right_list))
a = dict(zip(map(os.path.normcase, self.left_list), self.left_list))
b = dict(zip(map(os.path.normcase, self.right_list), self.right_list))
self.common = list(map(a.__getitem__, filter(b.__contains__, a)))
self.left_only = list(map(a.__getitem__, filterfalse(b.__contains__, a)))
self.right_only = list(map(b.__getitem__, filterfalse(a.__contains__, b)))

View File

@ -129,7 +129,7 @@ From all times, sorting has always been a Great Art! :-)
__all__ = ['heappush', 'heappop', 'heapify', 'heapreplace', 'merge',
'nlargest', 'nsmallest']
from itertools import islice, repeat, count, izip, tee
from itertools import islice, repeat, count, tee
from operator import itemgetter, neg
import bisect
@ -352,7 +352,7 @@ def nsmallest(n, iterable, key=None):
"""
in1, in2 = tee(iterable)
keys = in1 if key is None else map(key, in1)
it = izip(keys, count(), in2) # decorate
it = zip(keys, count(), in2) # decorate
result = _nsmallest(n, it)
return list(map(itemgetter(2), result)) # undecorate
@ -364,7 +364,7 @@ def nlargest(n, iterable, key=None):
"""
in1, in2 = tee(iterable)
keys = in1 if key is None else map(key, in1)
it = izip(keys, map(neg, count()), in2) # decorate
it = zip(keys, map(neg, count()), in2) # decorate
result = _nlargest(n, it)
return list(map(itemgetter(2), result)) # undecorate

View File

@ -79,7 +79,7 @@ class IterFuncStop:
def __next__(self):
raise StopIteration
from itertools import chain, map
from itertools import chain
def itermulti(seqn):
'Test multiple tiers of iterators'
return chain(map(lambda x:x, iterfunc(IterGen(Sequence(seqn)))))

View File

@ -1,4 +1,4 @@
import sys, itertools
import sys
import _ast
def to_tuple(t):
@ -142,7 +142,7 @@ def run_tests():
for input, output, kind in ((exec_tests, exec_results, "exec"),
(single_tests, single_results, "single"),
(eval_tests, eval_results, "eval")):
for i, o in itertools.izip(input, output):
for i, o in zip(input, output):
ast_tree = compile(i, "?", kind, 0x400)
tup = to_tuple(ast_tree)
assert tup == o, ("kind=%r\ninput=%r\nexpected=%r\ngot=%r" %

View File

@ -260,7 +260,7 @@ class S:
def __next__(self):
raise StopIteration
from itertools import chain, map
from itertools import chain
def L(seqn):
'Test multiple tiers of iterators'
return chain(map(lambda x:x, R(Ig(G(seqn)))))

View File

@ -8,8 +8,6 @@ import random
from functools import reduce
maxsize = test_support.MAX_Py_ssize_t
minsize = -maxsize-1
ifilter = filter
imap = map
def lzip(*args):
return list(zip(*args))
@ -313,16 +311,16 @@ class TestBasicOps(unittest.TestCase):
keyfunc.skip = 1
self.assertRaises(ExpectedError, gulp, [None, None], keyfunc)
def test_ifilter(self):
self.assertEqual(list(ifilter(isEven, range(6))), [0,2,4])
self.assertEqual(list(ifilter(None, [0,1,0,2,0])), [1,2])
self.assertEqual(list(ifilter(bool, [0,1,0,2,0])), [1,2])
self.assertEqual(take(4, ifilter(isEven, count())), [0,2,4,6])
self.assertRaises(TypeError, ifilter)
self.assertRaises(TypeError, ifilter, lambda x:x)
self.assertRaises(TypeError, ifilter, lambda x:x, range(6), 7)
self.assertRaises(TypeError, ifilter, isEven, 3)
self.assertRaises(TypeError, next, ifilter(range(6), range(6)))
def test_filter(self):
self.assertEqual(list(filter(isEven, range(6))), [0,2,4])
self.assertEqual(list(filter(None, [0,1,0,2,0])), [1,2])
self.assertEqual(list(filter(bool, [0,1,0,2,0])), [1,2])
self.assertEqual(take(4, filter(isEven, count())), [0,2,4,6])
self.assertRaises(TypeError, filter)
self.assertRaises(TypeError, filter, lambda x:x)
self.assertRaises(TypeError, filter, lambda x:x, range(6), 7)
self.assertRaises(TypeError, filter, isEven, 3)
self.assertRaises(TypeError, next, filter(range(6), range(6)))
def test_filterfalse(self):
self.assertEqual(list(filterfalse(isEven, range(6))), [1,3,5])
@ -335,28 +333,28 @@ class TestBasicOps(unittest.TestCase):
self.assertRaises(TypeError, filterfalse, isEven, 3)
self.assertRaises(TypeError, next, filterfalse(range(6), range(6)))
def test_izip(self):
# XXX This is rather silly now that builtin zip() calls izip()...
ans = [(x,y) for x, y in izip('abc',count())]
def test_zip(self):
# XXX This is rather silly now that builtin zip() calls zip()...
ans = [(x,y) for x, y in zip('abc',count())]
self.assertEqual(ans, [('a', 0), ('b', 1), ('c', 2)])
self.assertEqual(list(izip('abc', range(6))), lzip('abc', range(6)))
self.assertEqual(list(izip('abcdef', range(3))), lzip('abcdef', range(3)))
self.assertEqual(take(3,izip('abcdef', count())), lzip('abcdef', range(3)))
self.assertEqual(list(izip('abcdef')), lzip('abcdef'))
self.assertEqual(list(izip()), lzip())
self.assertRaises(TypeError, izip, 3)
self.assertRaises(TypeError, izip, range(3), 3)
self.assertEqual(list(zip('abc', range(6))), lzip('abc', range(6)))
self.assertEqual(list(zip('abcdef', range(3))), lzip('abcdef', range(3)))
self.assertEqual(take(3,zip('abcdef', count())), lzip('abcdef', range(3)))
self.assertEqual(list(zip('abcdef')), lzip('abcdef'))
self.assertEqual(list(zip()), lzip())
self.assertRaises(TypeError, zip, 3)
self.assertRaises(TypeError, zip, range(3), 3)
# Check tuple re-use (implementation detail)
self.assertEqual([tuple(list(pair)) for pair in izip('abc', 'def')],
self.assertEqual([tuple(list(pair)) for pair in zip('abc', 'def')],
lzip('abc', 'def'))
self.assertEqual([pair for pair in izip('abc', 'def')],
self.assertEqual([pair for pair in zip('abc', 'def')],
lzip('abc', 'def'))
ids = list(map(id, izip('abc', 'def')))
ids = list(map(id, zip('abc', 'def')))
self.assertEqual(min(ids), max(ids))
ids = list(map(id, list(izip('abc', 'def'))))
ids = list(map(id, list(zip('abc', 'def'))))
self.assertEqual(len(dict.fromkeys(ids)), len(ids))
def test_iziplongest(self):
def test_ziplongest(self):
for args in [
['abc', range(6)],
[range(6), 'abc'],
@ -378,7 +376,7 @@ class TestBasicOps(unittest.TestCase):
self.assertEqual(list(zip_longest('abcdef')), list(zip('abcdef')))
self.assertEqual(list(zip_longest('abc', 'defg', **{})),
list(izip(list('abc')+[None], 'defg'))) # empty keyword dict
list(zip(list('abc')+[None], 'defg'))) # empty keyword dict
self.assertRaises(TypeError, zip_longest, 3)
self.assertRaises(TypeError, zip_longest, range(3), 3)
@ -448,29 +446,29 @@ class TestBasicOps(unittest.TestCase):
list(r)
self.assertEqual(repr(r), 'repeat((1+0j), 0)')
def test_imap(self):
self.assertEqual(list(imap(operator.pow, range(3), range(1,7))),
def test_map(self):
self.assertEqual(list(map(operator.pow, range(3), range(1,7))),
[0**1, 1**2, 2**3])
def tupleize(*args):
return args
self.assertEqual(list(imap(tupleize, 'abc', range(5))),
self.assertEqual(list(map(tupleize, 'abc', range(5))),
[('a',0),('b',1),('c',2)])
self.assertEqual(list(imap(tupleize, 'abc', count())),
self.assertEqual(list(map(tupleize, 'abc', count())),
[('a',0),('b',1),('c',2)])
self.assertEqual(take(2,imap(tupleize, 'abc', count())),
self.assertEqual(take(2,map(tupleize, 'abc', count())),
[('a',0),('b',1)])
self.assertEqual(list(imap(operator.pow, [])), [])
self.assertRaises(TypeError, imap)
self.assertRaises(TypeError, list, imap(None, range(3), range(3)))
self.assertRaises(TypeError, imap, operator.neg)
self.assertRaises(TypeError, next, imap(10, range(5)))
self.assertRaises(ValueError, next, imap(errfunc, [4], [5]))
self.assertRaises(TypeError, next, imap(onearg, [4], [5]))
self.assertEqual(list(map(operator.pow, [])), [])
self.assertRaises(TypeError, map)
self.assertRaises(TypeError, list, map(None, range(3), range(3)))
self.assertRaises(TypeError, map, operator.neg)
self.assertRaises(TypeError, next, map(10, range(5)))
self.assertRaises(ValueError, next, map(errfunc, [4], [5]))
self.assertRaises(TypeError, next, map(onearg, [4], [5]))
def test_starmap(self):
self.assertEqual(list(starmap(operator.pow, zip(range(3), range(1,7)))),
[0**1, 1**2, 2**3])
self.assertEqual(take(3, starmap(operator.pow, izip(count(), count(1)))),
self.assertEqual(take(3, starmap(operator.pow, zip(count(), count(1)))),
[0**1, 1**2, 2**3])
self.assertEqual(list(starmap(operator.pow, [])), [])
self.assertEqual(list(starmap(operator.pow, [iter([4,5])])), [4**5])
@ -641,9 +639,9 @@ class TestBasicOps(unittest.TestCase):
self.assertRaises(ReferenceError, getattr, p, '__class__')
def test_StopIteration(self):
self.assertRaises(StopIteration, next, izip())
self.assertRaises(StopIteration, next, zip())
for f in (chain, cycle, izip, groupby):
for f in (chain, cycle, zip, groupby):
self.assertRaises(StopIteration, next, f([]))
self.assertRaises(StopIteration, next, f(StopNow()))
@ -659,7 +657,7 @@ class TestBasicOps(unittest.TestCase):
self.assertRaises(StopIteration, next, repeat(None, 0))
for f in (ifilter, filterfalse, imap, takewhile, dropwhile, starmap):
for f in (filter, filterfalse, map, takewhile, dropwhile, starmap):
self.assertRaises(StopIteration, next, f(lambda x:x, []))
self.assertRaises(StopIteration, next, f(lambda x:x, StopNow()))
@ -686,21 +684,21 @@ class TestGC(unittest.TestCase):
a = []
self.makecycle(groupby([a]*2, lambda x:x), a)
def test_ifilter(self):
def test_filter(self):
a = []
self.makecycle(ifilter(lambda x:True, [a]*2), a)
self.makecycle(filter(lambda x:True, [a]*2), a)
def test_filterfalse(self):
a = []
self.makecycle(filterfalse(lambda x:False, a), a)
def test_izip(self):
def test_zip(self):
a = []
self.makecycle(izip([a]*2, [a]*3), a)
self.makecycle(zip([a]*2, [a]*3), a)
def test_imap(self):
def test_map(self):
a = []
self.makecycle(imap(lambda x:x, [a]*2), a)
self.makecycle(map(lambda x:x, [a]*2), a)
def test_islice(self):
a = []
@ -792,7 +790,7 @@ class S:
def L(seqn):
'Test multiple tiers of iterators'
return chain(imap(lambda x:x, R(Ig(G(seqn)))))
return chain(map(lambda x:x, R(Ig(G(seqn)))))
class TestVariousIteratorArgs(unittest.TestCase):
@ -831,14 +829,14 @@ class TestVariousIteratorArgs(unittest.TestCase):
self.assertRaises(TypeError, groupby, N(s))
self.assertRaises(ZeroDivisionError, list, groupby(E(s)))
def test_ifilter(self):
def test_filter(self):
for s in (range(10), range(0), range(1000), (7,11), range(2000,2200,5)):
for g in (G, I, Ig, S, L, R):
self.assertEqual(list(ifilter(isEven, g(s))),
self.assertEqual(list(filter(isEven, g(s))),
[x for x in g(s) if isEven(x)])
self.assertRaises(TypeError, ifilter, isEven, X(s))
self.assertRaises(TypeError, ifilter, isEven, N(s))
self.assertRaises(ZeroDivisionError, list, ifilter(isEven, E(s)))
self.assertRaises(TypeError, filter, isEven, X(s))
self.assertRaises(TypeError, filter, isEven, N(s))
self.assertRaises(ZeroDivisionError, list, filter(isEven, E(s)))
def test_filterfalse(self):
for s in (range(10), range(0), range(1000), (7,11), range(2000,2200,5)):
@ -849,16 +847,16 @@ class TestVariousIteratorArgs(unittest.TestCase):
self.assertRaises(TypeError, filterfalse, isEven, N(s))
self.assertRaises(ZeroDivisionError, list, filterfalse(isEven, E(s)))
def test_izip(self):
def test_zip(self):
for s in ("123", "", range(1000), ('do', 1.2), range(2000,2200,5)):
for g in (G, I, Ig, S, L, R):
self.assertEqual(list(izip(g(s))), lzip(g(s)))
self.assertEqual(list(izip(g(s), g(s))), lzip(g(s), g(s)))
self.assertRaises(TypeError, izip, X(s))
self.assertRaises(TypeError, izip, N(s))
self.assertRaises(ZeroDivisionError, list, izip(E(s)))
self.assertEqual(list(zip(g(s))), lzip(g(s)))
self.assertEqual(list(zip(g(s), g(s))), lzip(g(s), g(s)))
self.assertRaises(TypeError, zip, X(s))
self.assertRaises(TypeError, zip, N(s))
self.assertRaises(ZeroDivisionError, list, zip(E(s)))
def test_iziplongest(self):
def test_ziplongest(self):
for s in ("123", "", range(1000), ('do', 1.2), range(2000,2200,5)):
for g in (G, I, Ig, S, L, R):
self.assertEqual(list(zip_longest(g(s))), list(zip(g(s))))
@ -867,16 +865,16 @@ class TestVariousIteratorArgs(unittest.TestCase):
self.assertRaises(TypeError, zip_longest, N(s))
self.assertRaises(ZeroDivisionError, list, zip_longest(E(s)))
def test_imap(self):
def test_map(self):
for s in (range(10), range(0), range(100), (7,11), range(20,50,5)):
for g in (G, I, Ig, S, L, R):
self.assertEqual(list(imap(onearg, g(s))),
self.assertEqual(list(map(onearg, g(s))),
[onearg(x) for x in g(s)])
self.assertEqual(list(imap(operator.pow, g(s), g(s))),
self.assertEqual(list(map(operator.pow, g(s), g(s))),
[x**x for x in g(s)])
self.assertRaises(TypeError, imap, onearg, X(s))
self.assertRaises(TypeError, imap, onearg, N(s))
self.assertRaises(ZeroDivisionError, list, imap(onearg, E(s)))
self.assertRaises(TypeError, map, onearg, X(s))
self.assertRaises(TypeError, map, onearg, N(s))
self.assertRaises(ZeroDivisionError, list, map(onearg, E(s)))
def test_islice(self):
for s in ("12345", "", range(1000), ('do', 1.2), range(2000,2200,5)):
@ -953,8 +951,8 @@ class RegressionTests(unittest.TestCase):
return value
items = list(tuple2)
items[1:1] = list(tuple1)
gen = imap(g, items)
z = izip(*[gen]*len(tuple1))
gen = map(g, items)
z = zip(*[gen]*len(tuple1))
next(z)
def f(t):
@ -1001,7 +999,7 @@ class RegressionTests(unittest.TestCase):
class SubclassWithKwargsTest(unittest.TestCase):
def test_keywords_in_subclass(self):
# count is not subclassable...
for cls in (repeat, izip, ifilter, filterfalse, chain, imap,
for cls in (repeat, zip, filter, filterfalse, chain, map,
starmap, islice, takewhile, dropwhile, cycle):
class Subclass(cls):
def __init__(self, newarg=None, *args):
@ -1017,7 +1015,7 @@ libreftest = """ Doctest for examples in the library reference: libitertools.tex
>>> amounts = [120.15, 764.05, 823.14]
>>> for checknum, amount in izip(count(1200), amounts):
>>> for checknum, amount in zip(count(1200), amounts):
... print('Check %d is for $%.2f' % (checknum, amount))
...
Check 1200 is for $120.15
@ -1025,7 +1023,7 @@ Check 1201 is for $764.05
Check 1202 is for $823.14
>>> import operator
>>> for cube in imap(operator.pow, range(1,4), repeat(3)):
>>> for cube in map(operator.pow, range(1,4), repeat(3)):
... print(cube)
...
1
@ -1070,14 +1068,14 @@ Samuele
... return list(islice(seq, n))
>>> def enumerate(iterable):
... return izip(count(), iterable)
... return zip(count(), iterable)
>>> def tabulate(function):
... "Return function(0), function(1), ..."
... return imap(function, count())
... return map(function, count())
>>> def iteritems(mapping):
... return izip(mapping.keys(), mapping.values())
... return zip(mapping.keys(), mapping.values())
>>> def nth(iterable, n):
... "Returns the nth item"
@ -1091,19 +1089,19 @@ Samuele
>>> def any(seq, pred=None):
... "Returns True if pred(x) is true for at least one element in the iterable"
... for elem in ifilter(pred, seq):
... for elem in filter(pred, seq):
... return True
... return False
>>> def no(seq, pred=None):
... "Returns True if pred(x) is false for every element in the iterable"
... for elem in ifilter(pred, seq):
... for elem in filter(pred, seq):
... return False
... return True
>>> def quantify(seq, pred=None):
... "Count how many times the predicate is true in the sequence"
... return sum(imap(pred, seq))
... return sum(map(pred, seq))
>>> def padnone(seq):
... "Returns the sequence elements and then returns None indefinitely"
@ -1114,7 +1112,7 @@ Samuele
... return chain(*repeat(seq, n))
>>> def dotproduct(vec1, vec2):
... return sum(imap(operator.mul, vec1, vec2))
... return sum(map(operator.mul, vec1, vec2))
>>> def flatten(listOfLists):
... return list(chain(*listOfLists))
@ -1134,7 +1132,7 @@ Samuele
... next(b)
... except StopIteration:
... pass
... return izip(a, b)
... return zip(a, b)
This is not part of the examples but it tests to make sure the definitions
perform as purported.
@ -1180,7 +1178,7 @@ False
[8, 8, 8, 8, 8]
>>> import random
>>> take(5, imap(int, repeatfunc(random.random)))
>>> take(5, map(int, repeatfunc(random.random)))
[0, 0, 0, 0, 0]
>>> list(pairwise('abcd'))

View File

@ -72,7 +72,7 @@ Core and Builtins
- Issue #1969: split and rsplit in bytearray are inconsistent
- map() and itertools.imap() no longer accept None for the first argument.
- map() and no longer accepts None for the first argument.
Use zip() instead.
- Issue #1769: Now int("- 1") is not allowed any more.
@ -123,6 +123,10 @@ Core and Builtins
Extension Modules
-----------------
- Code for itertools ifilter(), imap(), and izip() moved to bultins and
renamed to filter(), map(), and zip(). Also, renamed izip_longest()
to zip_longest() and ifilterfalse() to filterfalse().
- Issue #1762972: Readded the reload() function as imp.reload()
- Bug #2111: mmap segfaults when trying to write a block opened with PROT_READ

View File

@ -2352,193 +2352,6 @@ static PyTypeObject count_type = {
};
/* izip object ************************************************************/
#include "Python.h"
typedef struct {
PyObject_HEAD
Py_ssize_t tuplesize;
PyObject *ittuple; /* tuple of iterators */
PyObject *result;
} izipobject;
static PyTypeObject izip_type;
static PyObject *
izip_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
izipobject *lz;
Py_ssize_t i;
PyObject *ittuple; /* tuple of iterators */
PyObject *result;
Py_ssize_t tuplesize = PySequence_Length(args);
if (type == &izip_type && !_PyArg_NoKeywords("izip()", kwds))
return NULL;
/* args must be a tuple */
assert(PyTuple_Check(args));
/* obtain iterators */
ittuple = PyTuple_New(tuplesize);
if (ittuple == NULL)
return NULL;
for (i=0; i < tuplesize; ++i) {
PyObject *item = PyTuple_GET_ITEM(args, i);
PyObject *it = PyObject_GetIter(item);
if (it == NULL) {
if (PyErr_ExceptionMatches(PyExc_TypeError))
PyErr_Format(PyExc_TypeError,
"izip argument #%zd must support iteration",
i+1);
Py_DECREF(ittuple);
return NULL;
}
PyTuple_SET_ITEM(ittuple, i, it);
}
/* create a result holder */
result = PyTuple_New(tuplesize);
if (result == NULL) {
Py_DECREF(ittuple);
return NULL;
}
for (i=0 ; i < tuplesize ; i++) {
Py_INCREF(Py_None);
PyTuple_SET_ITEM(result, i, Py_None);
}
/* create izipobject structure */
lz = (izipobject *)type->tp_alloc(type, 0);
if (lz == NULL) {
Py_DECREF(ittuple);
Py_DECREF(result);
return NULL;
}
lz->ittuple = ittuple;
lz->tuplesize = tuplesize;
lz->result = result;
return (PyObject *)lz;
}
static void
izip_dealloc(izipobject *lz)
{
PyObject_GC_UnTrack(lz);
Py_XDECREF(lz->ittuple);
Py_XDECREF(lz->result);
Py_TYPE(lz)->tp_free(lz);
}
static int
izip_traverse(izipobject *lz, visitproc visit, void *arg)
{
Py_VISIT(lz->ittuple);
Py_VISIT(lz->result);
return 0;
}
static PyObject *
izip_next(izipobject *lz)
{
Py_ssize_t i;
Py_ssize_t tuplesize = lz->tuplesize;
PyObject *result = lz->result;
PyObject *it;
PyObject *item;
PyObject *olditem;
if (tuplesize == 0)
return NULL;
if (Py_REFCNT(result) == 1) {
Py_INCREF(result);
for (i=0 ; i < tuplesize ; i++) {
it = PyTuple_GET_ITEM(lz->ittuple, i);
assert(PyIter_Check(it));
item = (*Py_TYPE(it)->tp_iternext)(it);
if (item == NULL) {
Py_DECREF(result);
return NULL;
}
olditem = PyTuple_GET_ITEM(result, i);
PyTuple_SET_ITEM(result, i, item);
Py_DECREF(olditem);
}
} else {
result = PyTuple_New(tuplesize);
if (result == NULL)
return NULL;
for (i=0 ; i < tuplesize ; i++) {
it = PyTuple_GET_ITEM(lz->ittuple, i);
assert(PyIter_Check(it));
item = (*Py_TYPE(it)->tp_iternext)(it);
if (item == NULL) {
Py_DECREF(result);
return NULL;
}
PyTuple_SET_ITEM(result, i, item);
}
}
return result;
}
PyDoc_STRVAR(izip_doc,
"izip(iter1 [,iter2 [...]]) --> izip object\n\
\n\
Return a izip object whose .__next__() method returns a tuple where\n\
the i-th element comes from the i-th iterable argument. The .__next__()\n\
method continues until the shortest iterable in the argument sequence\n\
is exhausted and then it raises StopIteration. Works like the zip()\n\
function but consumes less memory by returning an iterator instead of\n\
a list.");
static PyTypeObject izip_type = {
PyVarObject_HEAD_INIT(NULL, 0)
"itertools.izip", /* tp_name */
sizeof(izipobject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)izip_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_BASETYPE, /* tp_flags */
izip_doc, /* tp_doc */
(traverseproc)izip_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
PyObject_SelfIter, /* tp_iter */
(iternextfunc)izip_next, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
izip_new, /* tp_new */
PyObject_GC_Del, /* tp_free */
};
/* repeat object ************************************************************/
typedef struct {
@ -2675,7 +2488,7 @@ static PyTypeObject repeat_type = {
PyObject_GC_Del, /* tp_free */
};
/* iziplongest object ************************************************************/
/* ziplongest object ************************************************************/
#include "Python.h"
@ -2686,14 +2499,14 @@ typedef struct {
PyObject *ittuple; /* tuple of iterators */
PyObject *result;
PyObject *fillvalue;
} iziplongestobject;
} ziplongestobject;
static PyTypeObject iziplongest_type;
static PyTypeObject ziplongest_type;
static PyObject *
zip_longest_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
iziplongestobject *lz;
ziplongestobject *lz;
Py_ssize_t i;
PyObject *ittuple; /* tuple of iterators */
PyObject *result;
@ -2741,8 +2554,8 @@ zip_longest_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
PyTuple_SET_ITEM(result, i, Py_None);
}
/* create iziplongestobject structure */
lz = (iziplongestobject *)type->tp_alloc(type, 0);
/* create ziplongestobject structure */
lz = (ziplongestobject *)type->tp_alloc(type, 0);
if (lz == NULL) {
Py_DECREF(ittuple);
Py_DECREF(result);
@ -2758,7 +2571,7 @@ zip_longest_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
}
static void
zip_longest_dealloc(iziplongestobject *lz)
zip_longest_dealloc(ziplongestobject *lz)
{
PyObject_GC_UnTrack(lz);
Py_XDECREF(lz->ittuple);
@ -2768,7 +2581,7 @@ zip_longest_dealloc(iziplongestobject *lz)
}
static int
zip_longest_traverse(iziplongestobject *lz, visitproc visit, void *arg)
zip_longest_traverse(ziplongestobject *lz, visitproc visit, void *arg)
{
Py_VISIT(lz->ittuple);
Py_VISIT(lz->result);
@ -2777,7 +2590,7 @@ zip_longest_traverse(iziplongestobject *lz, visitproc visit, void *arg)
}
static PyObject *
zip_longest_next(iziplongestobject *lz)
zip_longest_next(ziplongestobject *lz)
{
Py_ssize_t i;
Py_ssize_t tuplesize = lz->tuplesize;
@ -2859,10 +2672,10 @@ are exhausted, the fillvalue is substituted in their place. The fillvalue\n\
defaults to None or can be specified by a keyword argument.\n\
");
static PyTypeObject iziplongest_type = {
static PyTypeObject ziplongest_type = {
PyVarObject_HEAD_INIT(NULL, 0)
"itertools.zip_longest", /* tp_name */
sizeof(iziplongestobject), /* tp_basicsize */
sizeof(ziplongestobject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)zip_longest_dealloc, /* tp_dealloc */
@ -2914,7 +2727,6 @@ cycle(p) --> p0, p1, ... plast, p0, p1, ...\n\
repeat(elem [,n]) --> elem, elem, elem, ... endlessly or up to n times\n\
\n\
Iterators terminating on the shortest input sequence:\n\
izip(p, q, ...) --> (p[0], q[0]), (p[1], q[1]), ... \n\
zip_longest(p, q, ...) --> (p[0], q[0]), (p[1], q[1]), ... \n\
filterfalse(pred, seq) --> elements of seq where pred(elem) is False\n\
islice(seq, [start,] stop [, step]) --> elements from\n\
@ -2949,8 +2761,7 @@ inititertools(void)
&chain_type,
&filterfalse_type,
&count_type,
&izip_type,
&iziplongest_type,
&ziplongest_type,
&product_type,
&repeat_type,
&groupby_type,

View File

@ -230,172 +230,3 @@ PyTypeObject PyCallIter_Type = {
};
/*********************** Zip Iterator **************************/
/* Largely copied from itertools.c by Brian Holmes */
typedef struct zipiterobject_t {
PyObject_HEAD
PyTupleObject *it_tuple; /* Set to NULL when iterator is exhausted */
Py_ssize_t resultsize;
PyTupleObject *result; /* Reusable tuple for optimization */
} zipiterobject;
/* Forward */
PyObject *
_PyZip_CreateIter(PyObject* args)
{
Py_ssize_t i;
Py_ssize_t tuplesize;
PyObject* ziptuple;
PyObject* result;
struct zipiterobject_t* zipiter;
assert(PyTuple_Check(args));
if (Py_TYPE(&PyZipIter_Type) == NULL) {
if (PyType_Ready(&PyZipIter_Type) < 0)
return NULL;
}
tuplesize = PySequence_Length((PyObject*) args);
ziptuple = PyTuple_New(tuplesize);
if (ziptuple == NULL)
return NULL;
for (i = 0; i < tuplesize; i++) {
PyObject *o = PyTuple_GET_ITEM(args, i);
PyObject *it = PyObject_GetIter(o);
if (it == NULL) {
/* XXX Should we do this?
if (PyErr_ExceptionMatches(PyExc_TypeError))
PyErr_Format(PyExc_TypeError,
"zip argument #%zd must support iteration",
I+1);
*/
Py_DECREF(ziptuple);
return NULL;
}
PyTuple_SET_ITEM(ziptuple, i, it);
}
/* create a reusable result holder */
result = PyTuple_New(tuplesize);
if (result == NULL) {
Py_DECREF(ziptuple);
return NULL;
}
for (i = 0; i < tuplesize; i++) {
Py_INCREF(Py_None);
PyTuple_SET_ITEM(result, i, Py_None);
}
zipiter = PyObject_GC_New(zipiterobject, &PyZipIter_Type);
if (zipiter == NULL) {
Py_DECREF(ziptuple);
Py_DECREF(result);
return NULL;
}
zipiter->result = (PyTupleObject*) result;
zipiter->resultsize = tuplesize;
zipiter->it_tuple = (PyTupleObject *) ziptuple;
_PyObject_GC_TRACK(zipiter);
return (PyObject *)zipiter;
}
static void
zipiter_dealloc(zipiterobject *it)
{
_PyObject_GC_UNTRACK(it);
Py_XDECREF(it->it_tuple);
Py_XDECREF(it->result);
PyObject_GC_Del(it);
}
static int
zipiter_traverse(zipiterobject *it, visitproc visit, void *arg)
{
Py_VISIT(it->it_tuple);
Py_VISIT(it->result);
return 0;
}
static PyObject *
zipiter_next(zipiterobject *zit)
{
Py_ssize_t i;
Py_ssize_t tuplesize = zit->resultsize;
PyObject *result = (PyObject*) zit->result;
PyObject *olditem;
if (tuplesize == 0)
return NULL;
if (result->ob_refcnt == 1) {
Py_INCREF(result);
for (i = 0; i < tuplesize; i++) {
PyObject *it = PyTuple_GET_ITEM(zit->it_tuple, i);
PyObject *item;
assert(PyIter_Check(it));
item = (*it->ob_type->tp_iternext)(it);
if (item == NULL) {
Py_DECREF(result);
return NULL;
}
olditem = PyTuple_GET_ITEM(result, i);
PyTuple_SET_ITEM(result, i, item);
Py_DECREF(olditem);
}
} else {
result = PyTuple_New(tuplesize);
if (result == NULL)
return NULL;
for (i = 0; i < tuplesize; i++) {
PyObject *it = PyTuple_GET_ITEM(zit->it_tuple, i);
PyObject *item;
assert(PyIter_Check(it));
item = (*it->ob_type->tp_iternext)(it);
if (item == NULL) {
Py_DECREF(result);
return NULL;
}
PyTuple_SET_ITEM(result, i, item);
}
}
return result;
}
PyTypeObject PyZipIter_Type = {
PyVarObject_HEAD_INIT(0, 0)
"zip_iterator", /* tp_name */
sizeof(zipiterobject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)zipiter_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
0, /* tp_doc */
(traverseproc)zipiter_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weakzipoffset */
PyObject_SelfIter, /* tp_iter */
(iternextfunc)zipiter_next, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
};

View File

@ -1967,23 +1967,187 @@ When using a tuple as the second argument issubclass(X, (A, B, ...)),\n\
is a shortcut for issubclass(X, A) or issubclass(X, B) or ... (etc.).");
static PyObject*
builtin_zip(PyObject *self, PyObject *args)
typedef struct {
PyObject_HEAD
Py_ssize_t tuplesize;
PyObject *ittuple; /* tuple of iterators */
PyObject *result;
} zipobject;
PyTypeObject PyZip_Type;
static PyObject *
zip_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
zipobject *lz;
Py_ssize_t i;
PyObject *ittuple; /* tuple of iterators */
PyObject *result;
Py_ssize_t tuplesize = PySequence_Length(args);
if (type == &PyZip_Type && !_PyArg_NoKeywords("zip()", kwds))
return NULL;
/* args must be a tuple */
assert(PyTuple_Check(args));
return _PyZip_CreateIter(args);
/* obtain iterators */
ittuple = PyTuple_New(tuplesize);
if (ittuple == NULL)
return NULL;
for (i=0; i < tuplesize; ++i) {
PyObject *item = PyTuple_GET_ITEM(args, i);
PyObject *it = PyObject_GetIter(item);
if (it == NULL) {
if (PyErr_ExceptionMatches(PyExc_TypeError))
PyErr_Format(PyExc_TypeError,
"zip argument #%zd must support iteration",
i+1);
Py_DECREF(ittuple);
return NULL;
}
PyTuple_SET_ITEM(ittuple, i, it);
}
/* create a result holder */
result = PyTuple_New(tuplesize);
if (result == NULL) {
Py_DECREF(ittuple);
return NULL;
}
for (i=0 ; i < tuplesize ; i++) {
Py_INCREF(Py_None);
PyTuple_SET_ITEM(result, i, Py_None);
}
/* create zipobject structure */
lz = (zipobject *)type->tp_alloc(type, 0);
if (lz == NULL) {
Py_DECREF(ittuple);
Py_DECREF(result);
return NULL;
}
lz->ittuple = ittuple;
lz->tuplesize = tuplesize;
lz->result = result;
return (PyObject *)lz;
}
static void
zip_dealloc(zipobject *lz)
{
PyObject_GC_UnTrack(lz);
Py_XDECREF(lz->ittuple);
Py_XDECREF(lz->result);
Py_TYPE(lz)->tp_free(lz);
}
static int
zip_traverse(zipobject *lz, visitproc visit, void *arg)
{
Py_VISIT(lz->ittuple);
Py_VISIT(lz->result);
return 0;
}
static PyObject *
zip_next(zipobject *lz)
{
Py_ssize_t i;
Py_ssize_t tuplesize = lz->tuplesize;
PyObject *result = lz->result;
PyObject *it;
PyObject *item;
PyObject *olditem;
if (tuplesize == 0)
return NULL;
if (Py_REFCNT(result) == 1) {
Py_INCREF(result);
for (i=0 ; i < tuplesize ; i++) {
it = PyTuple_GET_ITEM(lz->ittuple, i);
assert(PyIter_Check(it));
item = (*Py_TYPE(it)->tp_iternext)(it);
if (item == NULL) {
Py_DECREF(result);
return NULL;
}
olditem = PyTuple_GET_ITEM(result, i);
PyTuple_SET_ITEM(result, i, item);
Py_DECREF(olditem);
}
} else {
result = PyTuple_New(tuplesize);
if (result == NULL)
return NULL;
for (i=0 ; i < tuplesize ; i++) {
it = PyTuple_GET_ITEM(lz->ittuple, i);
assert(PyIter_Check(it));
item = (*Py_TYPE(it)->tp_iternext)(it);
if (item == NULL) {
Py_DECREF(result);
return NULL;
}
PyTuple_SET_ITEM(result, i, item);
}
}
return result;
}
PyDoc_STRVAR(zip_doc,
"zip(it1 [, it2 [...]]) -> iter([(it1[0], it2[0] ...), ...])\n\
"zip(iter1 [,iter2 [...]]) --> zip object\n\
\n\
Return an iterator yielding tuples, where each tuple contains the\n\
corresponding element from each of the argument iterables.\n\
The returned iterator ends when the shortest argument iterable is exhausted.\n\
(This is identical to itertools.izip().)");
Return a zip object whose .__next__() method returns a tuple where\n\
the i-th element comes from the i-th iterable argument. The .__next__()\n\
method continues until the shortest iterable in the argument sequence\n\
is exhausted and then it raises StopIteration. Works like the zip()\n\
function but consumes less memory by returning an iterator instead of\n\
a list.");
PyTypeObject PyZip_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"zip", /* tp_name */
sizeof(zipobject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)zip_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_BASETYPE, /* tp_flags */
zip_doc, /* tp_doc */
(traverseproc)zip_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
PyObject_SelfIter, /* tp_iter */
(iternextfunc)zip_next, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
zip_new, /* tp_new */
PyObject_GC_Del, /* tp_free */
};
static PyMethodDef builtin_methods[] = {
@ -2028,7 +2192,6 @@ static PyMethodDef builtin_methods[] = {
{"sorted", (PyCFunction)builtin_sorted, METH_VARARGS | METH_KEYWORDS, sorted_doc},
{"sum", builtin_sum, METH_VARARGS, sum_doc},
{"vars", builtin_vars, METH_VARARGS, vars_doc},
{"zip", builtin_zip, METH_VARARGS, zip_doc},
{NULL, NULL},
};
@ -2097,6 +2260,7 @@ _PyBuiltin_Init(void)
SETBUILTIN("super", &PySuper_Type);
SETBUILTIN("tuple", &PyTuple_Type);
SETBUILTIN("type", &PyType_Type);
SETBUILTIN("zip", &PyZip_Type);
debug = PyBool_FromLong(Py_OptimizeFlag == 0);
if (PyDict_SetItemString(dict, "__debug__", debug) < 0) {
Py_XDECREF(debug);