📄 listobject.c
字号:
int count = 0;
int i;
for (i = 0; i < self->ob_size; i++) {
int cmp = PyObject_RichCompareBool(self->ob_item[i], v, Py_EQ);
if (cmp > 0)
count++;
else if (cmp < 0)
return NULL;
}
return PyInt_FromLong((long)count);
}
static PyObject *
listremove(PyListObject *self, PyObject *v)
{
int i;
for (i = 0; i < self->ob_size; i++) {
int cmp = PyObject_RichCompareBool(self->ob_item[i], v, Py_EQ);
if (cmp > 0) {
if (list_ass_slice(self, i, i+1,
(PyObject *)NULL) != 0)
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
else if (cmp < 0)
return NULL;
}
PyErr_SetString(PyExc_ValueError, "list.remove(x): x not in list");
return NULL;
}
static int
list_traverse(PyListObject *o, visitproc visit, void *arg)
{
int i, err;
PyObject *x;
for (i = o->ob_size; --i >= 0; ) {
x = o->ob_item[i];
if (x != NULL) {
err = visit(x, arg);
if (err)
return err;
}
}
return 0;
}
static int
list_clear(PyListObject *lp)
{
(void) PyList_SetSlice((PyObject *)lp, 0, lp->ob_size, 0);
return 0;
}
static PyObject *
list_richcompare(PyObject *v, PyObject *w, int op)
{
PyListObject *vl, *wl;
int i;
if (!PyList_Check(v) || !PyList_Check(w)) {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
vl = (PyListObject *)v;
wl = (PyListObject *)w;
if (vl->ob_size != wl->ob_size && (op == Py_EQ || op == Py_NE)) {
/* Shortcut: if the lengths differ, the lists differ */
PyObject *res;
if (op == Py_EQ)
res = Py_False;
else
res = Py_True;
Py_INCREF(res);
return res;
}
/* Search for the first index where items are different */
for (i = 0; i < vl->ob_size && i < wl->ob_size; i++) {
int k = PyObject_RichCompareBool(vl->ob_item[i],
wl->ob_item[i], Py_EQ);
if (k < 0)
return NULL;
if (!k)
break;
}
if (i >= vl->ob_size || i >= wl->ob_size) {
/* No more items to compare -- compare sizes */
int vs = vl->ob_size;
int ws = wl->ob_size;
int cmp;
PyObject *res;
switch (op) {
case Py_LT: cmp = vs < ws; break;
case Py_LE: cmp = vs <= ws; break;
case Py_EQ: cmp = vs == ws; break;
case Py_NE: cmp = vs != ws; break;
case Py_GT: cmp = vs > ws; break;
case Py_GE: cmp = vs >= ws; break;
default: return NULL; /* cannot happen */
}
if (cmp)
res = Py_True;
else
res = Py_False;
Py_INCREF(res);
return res;
}
/* We have an item that differs -- shortcuts for EQ/NE */
if (op == Py_EQ) {
Py_INCREF(Py_False);
return Py_False;
}
if (op == Py_NE) {
Py_INCREF(Py_True);
return Py_True;
}
/* Compare the final item again using the proper operator */
return PyObject_RichCompare(vl->ob_item[i], wl->ob_item[i], op);
}
/* Adapted from newer code by Tim */
static int
list_fill(PyListObject *result, PyObject *v)
{
PyObject *it; /* iter(v) */
int n; /* guess for result list size */
int i;
n = result->ob_size;
/* Special-case list(a_list), for speed. */
if (PyList_Check(v)) {
if (v == (PyObject *)result)
return 0; /* source is destination, we're done */
return list_ass_slice(result, 0, n, v);
}
/* Empty previous contents */
if (n != 0) {
if (list_ass_slice(result, 0, n, (PyObject *)NULL) != 0)
return -1;
}
/* Get iterator. There may be some low-level efficiency to be gained
* by caching the tp_iternext slot instead of using PyIter_Next()
* later, but premature optimization is the root etc.
*/
it = PyObject_GetIter(v);
if (it == NULL)
return -1;
/* Guess a result list size. */
n = -1; /* unknown */
if (PySequence_Check(v) &&
v->ob_type->tp_as_sequence->sq_length) {
n = PySequence_Size(v);
if (n < 0)
PyErr_Clear();
}
if (n < 0)
n = 8; /* arbitrary */
NRESIZE(result->ob_item, PyObject*, n);
if (result->ob_item == NULL) {
PyErr_NoMemory();
goto error;
}
for (i = 0; i < n; i++)
result->ob_item[i] = NULL;
result->ob_size = n;
/* Run iterator to exhaustion. */
for (i = 0; ; i++) {
PyObject *item = PyIter_Next(it);
if (item == NULL) {
if (PyErr_Occurred())
goto error;
break;
}
if (i < n)
PyList_SET_ITEM(result, i, item); /* steals ref */
else {
int status = ins1(result, result->ob_size, item);
Py_DECREF(item); /* append creates a new ref */
if (status < 0)
goto error;
}
}
/* Cut back result list if initial guess was too large. */
if (i < n && result != NULL) {
if (list_ass_slice(result, i, n, (PyObject *)NULL) != 0)
goto error;
}
Py_DECREF(it);
return 0;
error:
Py_DECREF(it);
return -1;
}
static int
list_init(PyListObject *self, PyObject *args, PyObject *kw)
{
PyObject *arg = NULL;
static const char *const kwlist[] = {"sequence", 0};
if (!PyArg_ParseTupleAndKeywords(args, kw, "|O:list", kwlist, &arg))
return -1;
if (arg != NULL)
return list_fill(self, arg);
if (self->ob_size > 0)
return list_ass_slice(self, 0, self->ob_size, (PyObject*)NULL);
return 0;
}
static long
list_nohash(PyObject *self)
{
PyErr_SetString(PyExc_TypeError, "list objects are unhashable");
return -1;
}
const static char append_doc[] =
#ifdef SYMBIAN
"";
#else
"L.append(object) -- append object to end";
#endif
const static char extend_doc[] =
#ifdef SYMBIAN
"";
#else
"L.extend(list) -- extend list by appending list elements";
#endif
const static char insert_doc[] =
#ifdef SYMBIAN
"";
#else
"L.insert(index, object) -- insert object before index";
#endif
const static char pop_doc[] =
#ifdef SYMBIAN
"";
#else
"L.pop([index]) -> item -- remove and return item at index (default last)";
#endif
const static char remove_doc[] =
#ifdef SYMBIAN
"";
#else
"L.remove(value) -- remove first occurrence of value";
#endif
const static char index_doc[] =
#ifdef SYMBIAN
"";
#else
"L.index(value) -> integer -- return index of first occurrence of value";
#endif
const static char count_doc[] =
#ifdef SYMBIAN
"";
#else
"L.count(value) -> integer -- return number of occurrences of value";
#endif
const static char reverse_doc[] =
#ifdef SYMBIAN
"";
#else
"L.reverse() -- reverse *IN PLACE*";
#endif
const static char sort_doc[] =
#ifdef SYMBIAN
"";
#else
"L.sort([cmpfunc]) -- sort *IN PLACE*; if given, cmpfunc(x, y) -> -1, 0, 1";
#endif
const static PyMethodDef list_methods[] = {
{"append", (PyCFunction)listappend, METH_O, append_doc},
{"insert", (PyCFunction)listinsert, METH_VARARGS, insert_doc},
{"extend", (PyCFunction)listextend, METH_O, extend_doc},
{"pop", (PyCFunction)listpop, METH_VARARGS, pop_doc},
{"remove", (PyCFunction)listremove, METH_O, remove_doc},
{"index", (PyCFunction)listindex, METH_O, index_doc},
{"count", (PyCFunction)listcount, METH_O, count_doc},
{"reverse", (PyCFunction)listreverse, METH_NOARGS, reverse_doc},
{"sort", (PyCFunction)listsort, METH_VARARGS, sort_doc},
{NULL, NULL} /* sentinel */
};
const static PySequenceMethods list_as_sequence = {
(inquiry)list_length, /* sq_length */
(binaryfunc)list_concat, /* sq_concat */
(intargfunc)list_repeat, /* sq_repeat */
(intargfunc)list_item, /* sq_item */
(intintargfunc)list_slice, /* sq_slice */
(intobjargproc)list_ass_item, /* sq_ass_item */
(intintobjargproc)list_ass_slice, /* sq_ass_slice */
(objobjproc)list_contains, /* sq_contains */
(binaryfunc)list_inplace_concat, /* sq_inplace_concat */
(intargfunc)list_inplace_repeat, /* sq_inplace_repeat */
};
const static char list_doc[] =
#ifdef SYMBIAN
"";
#else
"list() -> new list\n"
"list(sequence) -> new list initialized from sequence's items";
#endif
#ifndef SYMBIAN
PyTypeObject PyList_Type = {
PyObject_HEAD_INIT(&PyType_Type)
#else
const PyTypeObject c_PyList_Type = {
PyObject_HEAD_INIT(NULL)
#endif
0,
"list",
sizeof(PyListObject),
0,
(destructor)list_dealloc, /* tp_dealloc */
(printfunc)list_print, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
(reprfunc)list_repr, /* tp_repr */
0, /* tp_as_number */
&list_as_sequence, /* tp_as_sequence */
0, /* tp_as_mapping */
list_nohash, /* 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 */
list_doc, /* tp_doc */
(traverseproc)list_traverse, /* tp_traverse */
(inquiry)list_clear, /* tp_clear */
list_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
list_methods, /* 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 */
(initproc)list_init, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew, /* tp_new */
_PyObject_GC_Del, /* tp_free */
};
/* During a sort, we really can't have anyone modifying the list; it could
cause core dumps. Thus, we substitute a dummy type that raises an
explanatory exception when a modifying operation is used. Caveat:
comparisons may behave differently; but I guess it's a bad idea anyway to
compare a list that's being sorted... */
static PyObject *
immutable_list_op(void)
{
PyErr_SetString(PyExc_TypeError,
"a list cannot be modified while it is being sorted");
return NULL;
}
const static PyMethodDef immutable_list_methods[] = {
{"append", (PyCFunction)immutable_list_op, METH_VARARGS},
{"insert", (PyCFunction)immutable_list_op, METH_VARARGS},
{"extend", (PyCFunction)immutable_list_op, METH_O},
{"pop", (PyCFunction)immutable_list_op, METH_VARARGS},
{"remove", (PyCFunction)immutable_list_op, METH_VARARGS},
{"index", (PyCFunction)listindex, METH_O},
{"count", (PyCFunction)listcount, METH_O},
{"reverse", (PyCFunction)immutable_list_op, METH_VARARGS},
{"sort", (PyCFunction)immutable_list_op, METH_VARARGS},
{NULL, NULL} /* sentinel */
};
static int
immutable_list_ass(void)
{
immutable_list_op();
return -1;
}
const static PySequenceMethods immutable_list_as_sequence = {
(inquiry)list_length, /* sq_length */
(binaryfunc)list_concat, /* sq_concat */
(intargfunc)list_repeat, /* sq_repeat */
(intargfunc)list_item, /* sq_item */
(intintargfunc)list_slice, /* sq_slice */
(intobjargproc)immutable_list_ass, /* sq_ass_item */
(intintobjargproc)immutable_list_ass, /* sq_ass_slice */
(objobjproc)list_contains, /* sq_contains */
};
#ifndef SYMBIAN
static PyTypeObject immutable_list_type = {
PyObject_HEAD_INIT(&PyType_Type)
#else
const PyTypeObject c_immutable_list_type = {
PyObject_HEAD_INIT(NULL)
#endif
0,
"list (immutable, during sort)",
sizeof(PyListObject),
0,
0, /* Cannot happen */ /* tp_dealloc */
(printfunc)list_print, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* Won't be called */ /* tp_compare */
(reprfunc)list_repr, /* tp_repr */
0, /* tp_as_number */
&immutable_list_as_sequence, /* tp_as_sequence */
0, /* tp_as_mapping */
list_nohash, /* 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 */
list_doc, /* tp_doc */
(traverseproc)list_traverse, /* tp_traverse */
0, /* tp_clear */
list_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
immutable_list_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_init */
/* NOTE: This is *not* the standard list_type struct! */
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -