Issues 2186 and 2187. Move map() from itertools to builtins.
This commit is contained in:
parent
17301e9fab
commit
a6c6037f88
@ -22,9 +22,8 @@ The tools are designed to combine readily with one another. This makes it easy
|
|||||||
to construct more specialized tools succinctly and efficiently in pure Python.
|
to construct more specialized tools succinctly and efficiently in pure Python.
|
||||||
|
|
||||||
For instance, SML provides a tabulation tool: ``tabulate(f)`` which produces a
|
For instance, SML provides a tabulation tool: ``tabulate(f)`` which produces a
|
||||||
sequence ``f(0), f(1), ...``. This toolbox provides :func:`imap` and
|
sequence ``f(0), f(1), ...``. But, this effect can be achieved in Python
|
||||||
:func:`count` which can be combined to form ``imap(f, count())`` and produce an
|
by combining :func:`map` and :func:`count` to form ``map(f, count())``.
|
||||||
equivalent result.
|
|
||||||
|
|
||||||
Likewise, the functional tools are designed to work well with the high-speed
|
Likewise, the functional tools are designed to work well with the high-speed
|
||||||
functions provided by the :mod:`operator` module.
|
functions provided by the :mod:`operator` module.
|
||||||
@ -138,7 +137,7 @@ loops that truncate the stream.
|
|||||||
.. function:: count([n])
|
.. function:: count([n])
|
||||||
|
|
||||||
Make an iterator that returns consecutive integers starting with *n*. If not
|
Make an iterator that returns consecutive integers starting with *n*. If not
|
||||||
specified *n* defaults to zero. Often used as an argument to :func:`imap` to
|
specified *n* defaults to zero. Often used as an argument to :func:`map` to
|
||||||
generate consecutive data points. Also, used with :func:`izip` to add sequence
|
generate consecutive data points. Also, used with :func:`izip` to add sequence
|
||||||
numbers. Equivalent to::
|
numbers. Equivalent to::
|
||||||
|
|
||||||
@ -248,22 +247,6 @@ loops that truncate the stream.
|
|||||||
yield x
|
yield x
|
||||||
|
|
||||||
|
|
||||||
.. function:: imap(function, *iterables)
|
|
||||||
|
|
||||||
Make an iterator that computes the function using arguments from each of the
|
|
||||||
iterables. This function is the same as the built-in :func:`map` function.
|
|
||||||
Equivalent to::
|
|
||||||
|
|
||||||
def imap(function, *iterables):
|
|
||||||
iterables = [iter(it) for it in iterables)
|
|
||||||
while True:
|
|
||||||
args = [next(it) for it in iterables]
|
|
||||||
if function is None:
|
|
||||||
yield tuple(args)
|
|
||||||
else:
|
|
||||||
yield function(*args)
|
|
||||||
|
|
||||||
|
|
||||||
.. function:: islice(iterable, [start,] stop [, step])
|
.. function:: islice(iterable, [start,] stop [, step])
|
||||||
|
|
||||||
Make an iterator that returns selected elements from the iterable. If *start* is
|
Make an iterator that returns selected elements from the iterable. If *start* is
|
||||||
@ -421,7 +404,7 @@ loops that truncate the stream.
|
|||||||
.. function:: repeat(object[, times])
|
.. function:: repeat(object[, times])
|
||||||
|
|
||||||
Make an iterator that returns *object* over and over again. Runs indefinitely
|
Make an iterator that returns *object* over and over again. Runs indefinitely
|
||||||
unless the *times* argument is specified. Used as argument to :func:`imap` for
|
unless the *times* argument is specified. Used as argument to :func:`map` for
|
||||||
invariant parameters to the called function. Also used with :func:`izip` to
|
invariant parameters to the called function. Also used with :func:`izip` to
|
||||||
create an invariant part of a tuple record. Equivalent to::
|
create an invariant part of a tuple record. Equivalent to::
|
||||||
|
|
||||||
@ -437,9 +420,9 @@ loops that truncate the stream.
|
|||||||
.. function:: starmap(function, iterable)
|
.. function:: starmap(function, iterable)
|
||||||
|
|
||||||
Make an iterator that computes the function using arguments obtained from
|
Make an iterator that computes the function using arguments obtained from
|
||||||
the iterable. Used instead of :func:`imap` when argument parameters are already
|
the iterable. Used instead of :func:`map` when argument parameters are already
|
||||||
grouped in tuples from a single iterable (the data has been "pre-zipped"). The
|
grouped in tuples from a single iterable (the data has been "pre-zipped"). The
|
||||||
difference between :func:`imap` and :func:`starmap` parallels the distinction
|
difference between :func:`map` and :func:`starmap` parallels the distinction
|
||||||
between ``function(a,b)`` and ``function(*c)``. Equivalent to::
|
between ``function(a,b)`` and ``function(*c)``. Equivalent to::
|
||||||
|
|
||||||
def starmap(function, iterable):
|
def starmap(function, iterable):
|
||||||
@ -507,7 +490,7 @@ can be combined. ::
|
|||||||
Check 1202 is for $823.14
|
Check 1202 is for $823.14
|
||||||
|
|
||||||
>>> import operator
|
>>> import operator
|
||||||
>>> for cube in imap(operator.pow, range(1,5), repeat(3)):
|
>>> for cube in map(operator.pow, range(1,5), repeat(3)):
|
||||||
... print(cube)
|
... print(cube)
|
||||||
...
|
...
|
||||||
1
|
1
|
||||||
@ -577,7 +560,7 @@ which incur interpreter overhead. ::
|
|||||||
|
|
||||||
def tabulate(function):
|
def tabulate(function):
|
||||||
"Return function(0), function(1), ..."
|
"Return function(0), function(1), ..."
|
||||||
return imap(function, count())
|
return map(function, count())
|
||||||
|
|
||||||
def nth(iterable, n):
|
def nth(iterable, n):
|
||||||
"Returns the nth item or raise StopIteration"
|
"Returns the nth item or raise StopIteration"
|
||||||
@ -603,7 +586,7 @@ which incur interpreter overhead. ::
|
|||||||
|
|
||||||
def quantify(seq, pred=None):
|
def quantify(seq, pred=None):
|
||||||
"Count how many times the predicate is true in the sequence"
|
"Count how many times the predicate is true in the sequence"
|
||||||
return sum(imap(pred, seq))
|
return sum(map(pred, seq))
|
||||||
|
|
||||||
def padnone(seq):
|
def padnone(seq):
|
||||||
"""Returns the sequence elements and then returns None indefinitely.
|
"""Returns the sequence elements and then returns None indefinitely.
|
||||||
@ -617,7 +600,7 @@ which incur interpreter overhead. ::
|
|||||||
return chain.from_iterable(repeat(seq, n))
|
return chain.from_iterable(repeat(seq, n))
|
||||||
|
|
||||||
def dotproduct(vec1, vec2):
|
def dotproduct(vec1, vec2):
|
||||||
return sum(imap(operator.mul, vec1, vec2))
|
return sum(map(operator.mul, vec1, vec2))
|
||||||
|
|
||||||
def flatten(listOfLists):
|
def flatten(listOfLists):
|
||||||
return list(chain.from_iterable(listOfLists))
|
return list(chain.from_iterable(listOfLists))
|
||||||
|
@ -12,7 +12,7 @@ Functions:
|
|||||||
import os
|
import os
|
||||||
import stat
|
import stat
|
||||||
import warnings
|
import warnings
|
||||||
from itertools import ifilterfalse, imap, izip
|
from itertools import ifilterfalse, izip
|
||||||
|
|
||||||
__all__ = ["cmp","dircmp","cmpfiles"]
|
__all__ = ["cmp","dircmp","cmpfiles"]
|
||||||
|
|
||||||
@ -130,8 +130,8 @@ class dircmp:
|
|||||||
self.right_list.sort()
|
self.right_list.sort()
|
||||||
|
|
||||||
def phase1(self): # Compute common names
|
def phase1(self): # Compute common names
|
||||||
a = dict(izip(imap(os.path.normcase, self.left_list), self.left_list))
|
a = dict(izip(map(os.path.normcase, self.left_list), self.left_list))
|
||||||
b = dict(izip(imap(os.path.normcase, self.right_list), self.right_list))
|
b = dict(izip(map(os.path.normcase, self.right_list), self.right_list))
|
||||||
self.common = list(map(a.__getitem__, filter(b.__contains__, a)))
|
self.common = list(map(a.__getitem__, filter(b.__contains__, a)))
|
||||||
self.left_only = list(map(a.__getitem__, ifilterfalse(b.__contains__, a)))
|
self.left_only = list(map(a.__getitem__, ifilterfalse(b.__contains__, a)))
|
||||||
self.right_only = list(map(b.__getitem__, ifilterfalse(a.__contains__, b)))
|
self.right_only = list(map(b.__getitem__, ifilterfalse(a.__contains__, b)))
|
||||||
|
@ -79,10 +79,10 @@ class IterFuncStop:
|
|||||||
def __next__(self):
|
def __next__(self):
|
||||||
raise StopIteration
|
raise StopIteration
|
||||||
|
|
||||||
from itertools import chain, imap
|
from itertools import chain, map
|
||||||
def itermulti(seqn):
|
def itermulti(seqn):
|
||||||
'Test multiple tiers of iterators'
|
'Test multiple tiers of iterators'
|
||||||
return chain(imap(lambda x:x, iterfunc(IterGen(Sequence(seqn)))))
|
return chain(map(lambda x:x, iterfunc(IterGen(Sequence(seqn)))))
|
||||||
|
|
||||||
class CommonTest(unittest.TestCase):
|
class CommonTest(unittest.TestCase):
|
||||||
# The type to be tested
|
# The type to be tested
|
||||||
|
@ -260,10 +260,10 @@ class S:
|
|||||||
def __next__(self):
|
def __next__(self):
|
||||||
raise StopIteration
|
raise StopIteration
|
||||||
|
|
||||||
from itertools import chain, imap
|
from itertools import chain, map
|
||||||
def L(seqn):
|
def L(seqn):
|
||||||
'Test multiple tiers of iterators'
|
'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 TestErrorHandling(unittest.TestCase):
|
class TestErrorHandling(unittest.TestCase):
|
||||||
# only for C implementation
|
# only for C implementation
|
||||||
|
@ -9,6 +9,7 @@ from functools import reduce
|
|||||||
maxsize = test_support.MAX_Py_ssize_t
|
maxsize = test_support.MAX_Py_ssize_t
|
||||||
minsize = -maxsize-1
|
minsize = -maxsize-1
|
||||||
ifilter = filter
|
ifilter = filter
|
||||||
|
imap = map
|
||||||
|
|
||||||
def lzip(*args):
|
def lzip(*args):
|
||||||
return list(zip(*args))
|
return list(zip(*args))
|
||||||
|
@ -1560,10 +1560,10 @@ class S:
|
|||||||
def __next__(self):
|
def __next__(self):
|
||||||
raise StopIteration
|
raise StopIteration
|
||||||
|
|
||||||
from itertools import chain, imap
|
from itertools import chain
|
||||||
def L(seqn):
|
def L(seqn):
|
||||||
'Test multiple tiers of iterators'
|
'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):
|
class TestVariousIteratorArgs(unittest.TestCase):
|
||||||
|
|
||||||
|
@ -1418,155 +1418,6 @@ static PyTypeObject starmap_type = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* imap object ************************************************************/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
PyObject_HEAD
|
|
||||||
PyObject *iters;
|
|
||||||
PyObject *func;
|
|
||||||
} imapobject;
|
|
||||||
|
|
||||||
static PyTypeObject imap_type;
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
imap_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
||||||
{
|
|
||||||
PyObject *it, *iters, *func;
|
|
||||||
imapobject *lz;
|
|
||||||
Py_ssize_t numargs, i;
|
|
||||||
|
|
||||||
if (type == &imap_type && !_PyArg_NoKeywords("imap()", kwds))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
numargs = PyTuple_Size(args);
|
|
||||||
if (numargs < 2) {
|
|
||||||
PyErr_SetString(PyExc_TypeError,
|
|
||||||
"imap() must have at least two arguments.");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
iters = PyTuple_New(numargs-1);
|
|
||||||
if (iters == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
for (i=1 ; i<numargs ; i++) {
|
|
||||||
/* Get iterator. */
|
|
||||||
it = PyObject_GetIter(PyTuple_GET_ITEM(args, i));
|
|
||||||
if (it == NULL) {
|
|
||||||
Py_DECREF(iters);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
PyTuple_SET_ITEM(iters, i-1, it);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create imapobject structure */
|
|
||||||
lz = (imapobject *)type->tp_alloc(type, 0);
|
|
||||||
if (lz == NULL) {
|
|
||||||
Py_DECREF(iters);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
lz->iters = iters;
|
|
||||||
func = PyTuple_GET_ITEM(args, 0);
|
|
||||||
Py_INCREF(func);
|
|
||||||
lz->func = func;
|
|
||||||
|
|
||||||
return (PyObject *)lz;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
imap_dealloc(imapobject *lz)
|
|
||||||
{
|
|
||||||
PyObject_GC_UnTrack(lz);
|
|
||||||
Py_XDECREF(lz->iters);
|
|
||||||
Py_XDECREF(lz->func);
|
|
||||||
Py_TYPE(lz)->tp_free(lz);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
imap_traverse(imapobject *lz, visitproc visit, void *arg)
|
|
||||||
{
|
|
||||||
Py_VISIT(lz->iters);
|
|
||||||
Py_VISIT(lz->func);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
imap_next(imapobject *lz)
|
|
||||||
{
|
|
||||||
PyObject *val;
|
|
||||||
PyObject *argtuple;
|
|
||||||
PyObject *result;
|
|
||||||
Py_ssize_t numargs, i;
|
|
||||||
|
|
||||||
numargs = PyTuple_Size(lz->iters);
|
|
||||||
argtuple = PyTuple_New(numargs);
|
|
||||||
if (argtuple == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
for (i=0 ; i<numargs ; i++) {
|
|
||||||
val = PyIter_Next(PyTuple_GET_ITEM(lz->iters, i));
|
|
||||||
if (val == NULL) {
|
|
||||||
Py_DECREF(argtuple);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
PyTuple_SET_ITEM(argtuple, i, val);
|
|
||||||
}
|
|
||||||
result = PyObject_Call(lz->func, argtuple, NULL);
|
|
||||||
Py_DECREF(argtuple);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(imap_doc,
|
|
||||||
"imap(func, *iterables) --> imap object\n\
|
|
||||||
\n\
|
|
||||||
Make an iterator that computes the function using arguments from\n\
|
|
||||||
each of the iterables. Stops when the shortest iterable is exhausted.");
|
|
||||||
|
|
||||||
static PyTypeObject imap_type = {
|
|
||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
|
||||||
"itertools.imap", /* tp_name */
|
|
||||||
sizeof(imapobject), /* tp_basicsize */
|
|
||||||
0, /* tp_itemsize */
|
|
||||||
/* methods */
|
|
||||||
(destructor)imap_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 */
|
|
||||||
imap_doc, /* tp_doc */
|
|
||||||
(traverseproc)imap_traverse, /* tp_traverse */
|
|
||||||
0, /* tp_clear */
|
|
||||||
0, /* tp_richcompare */
|
|
||||||
0, /* tp_weaklistoffset */
|
|
||||||
PyObject_SelfIter, /* tp_iter */
|
|
||||||
(iternextfunc)imap_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 */
|
|
||||||
imap_new, /* tp_new */
|
|
||||||
PyObject_GC_Del, /* tp_free */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* chain object ************************************************************/
|
/* chain object ************************************************************/
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -3068,7 +2919,6 @@ izip_longest(p, q, ...) --> (p[0], q[0]), (p[1], q[1]), ... \n\
|
|||||||
ifilterfalse(pred, seq) --> elements of seq where pred(elem) is False\n\
|
ifilterfalse(pred, seq) --> elements of seq where pred(elem) is False\n\
|
||||||
islice(seq, [start,] stop [, step]) --> elements from\n\
|
islice(seq, [start,] stop [, step]) --> elements from\n\
|
||||||
seq[start:stop:step]\n\
|
seq[start:stop:step]\n\
|
||||||
imap(fun, p, q, ...) --> fun(p0, q0), fun(p1, q1), ...\n\
|
|
||||||
starmap(fun, seq) --> fun(*seq[0]), fun(*seq[1]), ...\n\
|
starmap(fun, seq) --> fun(*seq[0]), fun(*seq[1]), ...\n\
|
||||||
tee(it, n=2) --> (it1, it2 , ... itn) splits one iterator into n\n\
|
tee(it, n=2) --> (it1, it2 , ... itn) splits one iterator into n\n\
|
||||||
chain(p, q, ...) --> p0, p1, ... plast, q0, q1, ... \n\
|
chain(p, q, ...) --> p0, p1, ... plast, q0, q1, ... \n\
|
||||||
@ -3096,7 +2946,6 @@ inititertools(void)
|
|||||||
&takewhile_type,
|
&takewhile_type,
|
||||||
&islice_type,
|
&islice_type,
|
||||||
&starmap_type,
|
&starmap_type,
|
||||||
&imap_type,
|
|
||||||
&chain_type,
|
&chain_type,
|
||||||
&ifilterfalse_type,
|
&ifilterfalse_type,
|
||||||
&count_type,
|
&count_type,
|
||||||
|
@ -864,31 +864,153 @@ Return the identity of an object. This is guaranteed to be unique among\n\
|
|||||||
simultaneously existing objects. (Hint: it's the object's memory address.)");
|
simultaneously existing objects. (Hint: it's the object's memory address.)");
|
||||||
|
|
||||||
|
|
||||||
|
/* map object ************************************************************/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyObject_HEAD
|
||||||
|
PyObject *iters;
|
||||||
|
PyObject *func;
|
||||||
|
} mapobject;
|
||||||
|
|
||||||
|
PyTypeObject PyMap_Type;
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
builtin_map(PyObject *self, PyObject *args)
|
map_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
{
|
{
|
||||||
PyObject *itertools, *imap, *result;
|
PyObject *it, *iters, *func;
|
||||||
itertools = PyImport_ImportModuleNoBlock("itertools");
|
mapobject *lz;
|
||||||
if (itertools == NULL)
|
Py_ssize_t numargs, i;
|
||||||
|
|
||||||
|
if (type == &PyMap_Type && !_PyArg_NoKeywords("map()", kwds))
|
||||||
return NULL;
|
return NULL;
|
||||||
imap = PyObject_GetAttrString(itertools, "imap");
|
|
||||||
Py_DECREF(itertools);
|
numargs = PyTuple_Size(args);
|
||||||
if (imap == NULL)
|
if (numargs < 2) {
|
||||||
|
PyErr_SetString(PyExc_TypeError,
|
||||||
|
"map() must have at least two arguments.");
|
||||||
return NULL;
|
return NULL;
|
||||||
result = PyObject_Call(imap, args, NULL);
|
}
|
||||||
Py_DECREF(imap);
|
|
||||||
|
iters = PyTuple_New(numargs-1);
|
||||||
|
if (iters == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i=1 ; i<numargs ; i++) {
|
||||||
|
/* Get iterator. */
|
||||||
|
it = PyObject_GetIter(PyTuple_GET_ITEM(args, i));
|
||||||
|
if (it == NULL) {
|
||||||
|
Py_DECREF(iters);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
PyTuple_SET_ITEM(iters, i-1, it);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create mapobject structure */
|
||||||
|
lz = (mapobject *)type->tp_alloc(type, 0);
|
||||||
|
if (lz == NULL) {
|
||||||
|
Py_DECREF(iters);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
lz->iters = iters;
|
||||||
|
func = PyTuple_GET_ITEM(args, 0);
|
||||||
|
Py_INCREF(func);
|
||||||
|
lz->func = func;
|
||||||
|
|
||||||
|
return (PyObject *)lz;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
map_dealloc(mapobject *lz)
|
||||||
|
{
|
||||||
|
PyObject_GC_UnTrack(lz);
|
||||||
|
Py_XDECREF(lz->iters);
|
||||||
|
Py_XDECREF(lz->func);
|
||||||
|
Py_TYPE(lz)->tp_free(lz);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
map_traverse(mapobject *lz, visitproc visit, void *arg)
|
||||||
|
{
|
||||||
|
Py_VISIT(lz->iters);
|
||||||
|
Py_VISIT(lz->func);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
map_next(mapobject *lz)
|
||||||
|
{
|
||||||
|
PyObject *val;
|
||||||
|
PyObject *argtuple;
|
||||||
|
PyObject *result;
|
||||||
|
Py_ssize_t numargs, i;
|
||||||
|
|
||||||
|
numargs = PyTuple_Size(lz->iters);
|
||||||
|
argtuple = PyTuple_New(numargs);
|
||||||
|
if (argtuple == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i=0 ; i<numargs ; i++) {
|
||||||
|
val = PyIter_Next(PyTuple_GET_ITEM(lz->iters, i));
|
||||||
|
if (val == NULL) {
|
||||||
|
Py_DECREF(argtuple);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
PyTuple_SET_ITEM(argtuple, i, val);
|
||||||
|
}
|
||||||
|
result = PyObject_Call(lz->func, argtuple, NULL);
|
||||||
|
Py_DECREF(argtuple);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(map_doc,
|
PyDoc_STRVAR(map_doc,
|
||||||
"map(function, iterable[, iterable, ...]) -> iterator\n\
|
"map(func, *iterables) --> map object\n\
|
||||||
\n\
|
\n\
|
||||||
Return an iterator yielding the results of applying the function to the\n\
|
Make an iterator that computes the function using arguments from\n\
|
||||||
items of the argument iterables(s). If more than one iterable is given,\n\
|
each of the iterables. Stops when the shortest iterable is exhausted.");
|
||||||
the function is called with an argument list consisting of the\n\
|
|
||||||
corresponding item of each iterable, until an iterable is exhausted.\n\
|
|
||||||
(This is identical to itertools.imap().)");
|
|
||||||
|
|
||||||
|
PyTypeObject PyMap_Type = {
|
||||||
|
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
||||||
|
"map", /* tp_name */
|
||||||
|
sizeof(mapobject), /* tp_basicsize */
|
||||||
|
0, /* tp_itemsize */
|
||||||
|
/* methods */
|
||||||
|
(destructor)map_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 */
|
||||||
|
map_doc, /* tp_doc */
|
||||||
|
(traverseproc)map_traverse, /* tp_traverse */
|
||||||
|
0, /* tp_clear */
|
||||||
|
0, /* tp_richcompare */
|
||||||
|
0, /* tp_weaklistoffset */
|
||||||
|
PyObject_SelfIter, /* tp_iter */
|
||||||
|
(iternextfunc)map_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 */
|
||||||
|
map_new, /* tp_new */
|
||||||
|
PyObject_GC_Del, /* tp_free */
|
||||||
|
};
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
builtin_next(PyObject *self, PyObject *args)
|
builtin_next(PyObject *self, PyObject *args)
|
||||||
@ -1893,7 +2015,6 @@ static PyMethodDef builtin_methods[] = {
|
|||||||
{"iter", builtin_iter, METH_VARARGS, iter_doc},
|
{"iter", builtin_iter, METH_VARARGS, iter_doc},
|
||||||
{"len", builtin_len, METH_O, len_doc},
|
{"len", builtin_len, METH_O, len_doc},
|
||||||
{"locals", (PyCFunction)builtin_locals, METH_NOARGS, locals_doc},
|
{"locals", (PyCFunction)builtin_locals, METH_NOARGS, locals_doc},
|
||||||
{"map", builtin_map, METH_VARARGS, map_doc},
|
|
||||||
{"max", (PyCFunction)builtin_max, METH_VARARGS | METH_KEYWORDS, max_doc},
|
{"max", (PyCFunction)builtin_max, METH_VARARGS | METH_KEYWORDS, max_doc},
|
||||||
{"min", (PyCFunction)builtin_min, METH_VARARGS | METH_KEYWORDS, min_doc},
|
{"min", (PyCFunction)builtin_min, METH_VARARGS | METH_KEYWORDS, min_doc},
|
||||||
{"next", (PyCFunction)builtin_next, METH_VARARGS, next_doc},
|
{"next", (PyCFunction)builtin_next, METH_VARARGS, next_doc},
|
||||||
@ -1965,6 +2086,7 @@ _PyBuiltin_Init(void)
|
|||||||
SETBUILTIN("property", &PyProperty_Type);
|
SETBUILTIN("property", &PyProperty_Type);
|
||||||
SETBUILTIN("int", &PyLong_Type);
|
SETBUILTIN("int", &PyLong_Type);
|
||||||
SETBUILTIN("list", &PyList_Type);
|
SETBUILTIN("list", &PyList_Type);
|
||||||
|
SETBUILTIN("map", &PyMap_Type);
|
||||||
SETBUILTIN("object", &PyBaseObject_Type);
|
SETBUILTIN("object", &PyBaseObject_Type);
|
||||||
SETBUILTIN("range", &PyRange_Type);
|
SETBUILTIN("range", &PyRange_Type);
|
||||||
SETBUILTIN("reversed", &PyReversed_Type);
|
SETBUILTIN("reversed", &PyReversed_Type);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user