📄 tupleobject.c
字号:
}
#define b ((PyTupleObject *)bb)
size = a->ob_size + b->ob_size;
if (size < 0)
return PyErr_NoMemory();
np = (PyTupleObject *) PyTuple_New(size);
if (np == NULL) {
return NULL;
}
for (i = 0; i < a->ob_size; i++) {
PyObject *v = a->ob_item[i];
Py_INCREF(v);
np->ob_item[i] = v;
}
for (i = 0; i < b->ob_size; i++) {
PyObject *v = b->ob_item[i];
Py_INCREF(v);
np->ob_item[i + a->ob_size] = v;
}
return (PyObject *)np;
#undef b
}
static PyObject *
tuplerepeat(PyTupleObject *a, int n)
{
int i, j;
int size;
PyTupleObject *np;
PyObject **p;
if (n < 0)
n = 0;
if (a->ob_size == 0 || n == 1) {
if (PyTuple_CheckExact(a)) {
/* Since tuples are immutable, we can return a shared
copy in this case */
Py_INCREF(a);
return (PyObject *)a;
}
if (a->ob_size == 0)
return PyTuple_New(0);
}
size = a->ob_size * n;
if (size/a->ob_size != n)
return PyErr_NoMemory();
np = (PyTupleObject *) PyTuple_New(size);
if (np == NULL)
return NULL;
p = np->ob_item;
for (i = 0; i < n; i++) {
for (j = 0; j < a->ob_size; j++) {
*p = a->ob_item[j];
Py_INCREF(*p);
p++;
}
}
return (PyObject *) np;
}
static int
tupletraverse(PyTupleObject *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 PyObject *
tuplerichcompare(PyObject *v, PyObject *w, int op)
{
PyTupleObject *vt, *wt;
int i;
int vlen, wlen;
if (!PyTuple_Check(v) || !PyTuple_Check(w)) {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
vt = (PyTupleObject *)v;
wt = (PyTupleObject *)w;
vlen = vt->ob_size;
wlen = wt->ob_size;
/* Note: the corresponding code for lists has an "early out" test
* here when op is EQ or NE and the lengths differ. That pays there,
* but Tim was unable to find any real code where EQ/NE tuple
* compares don't have the same length, so testing for it here would
* have cost without benefit.
*/
/* Search for the first index where items are different.
* Note that because tuples are immutable, it's safe to reuse
* vlen and wlen across the comparison calls.
*/
for (i = 0; i < vlen && i < wlen; i++) {
int k = PyObject_RichCompareBool(vt->ob_item[i],
wt->ob_item[i], Py_EQ);
if (k < 0)
return NULL;
if (!k)
break;
}
if (i >= vlen || i >= wlen) {
/* No more items to compare -- compare sizes */
int cmp;
PyObject *res;
switch (op) {
case Py_LT: cmp = vlen < wlen; break;
case Py_LE: cmp = vlen <= wlen; break;
case Py_EQ: cmp = vlen == wlen; break;
case Py_NE: cmp = vlen != wlen; break;
case Py_GT: cmp = vlen > wlen; break;
case Py_GE: cmp = vlen >= wlen; 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(vt->ob_item[i], wt->ob_item[i], op);
}
staticforward PyObject *
tuple_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
static PyObject *
tuple_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *arg = NULL;
static const char *const kwlist[] = {"sequence", 0};
if (type != &PyTuple_Type)
return tuple_subtype_new(type, args, kwds);
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:tuple", kwlist, &arg))
return NULL;
if (arg == NULL)
return PyTuple_New(0);
else
return PySequence_Tuple(arg);
}
static PyObject *
tuple_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *tmp, *new, *item;
int i, n;
assert(PyType_IsSubtype(type, &PyTuple_Type));
tmp = tuple_new(&PyTuple_Type, args, kwds);
if (tmp == NULL)
return NULL;
assert(PyTuple_Check(tmp));
new = type->tp_alloc(type, n = PyTuple_GET_SIZE(tmp));
if (new == NULL)
return NULL;
for (i = 0; i < n; i++) {
item = PyTuple_GET_ITEM(tmp, i);
Py_INCREF(item);
PyTuple_SET_ITEM(new, i, item);
}
Py_DECREF(tmp);
return new;
}
const static char tuple_doc[] =
#ifdef SYMBIAN
"";
#else
"tuple() -> an empty tuple\n"
"tuple(sequence) -> tuple initialized from sequence's items\n"
"\n"
"If the argument is a tuple, the return value is the same object.";
#endif
const static PySequenceMethods tuple_as_sequence = {
(inquiry)tuplelength, /* sq_length */
(binaryfunc)tupleconcat, /* sq_concat */
(intargfunc)tuplerepeat, /* sq_repeat */
(intargfunc)tupleitem, /* sq_item */
(intintargfunc)tupleslice, /* sq_slice */
0, /* sq_ass_item */
0, /* sq_ass_slice */
(objobjproc)tuplecontains, /* sq_contains */
};
#ifndef SYMBIAN
PyTypeObject PyTuple_Type = {
PyObject_HEAD_INIT(&PyType_Type)
#else
const PyTypeObject c_PyTuple_Type = {
PyObject_HEAD_INIT(NULL)
#endif
0,
"tuple",
sizeof(PyTupleObject) - sizeof(PyObject *),
sizeof(PyObject *),
(destructor)tupledealloc, /* tp_dealloc */
(printfunc)tupleprint, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
(reprfunc)tuplerepr, /* tp_repr */
0, /* tp_as_number */
&tuple_as_sequence, /* tp_as_sequence */
0, /* tp_as_mapping */
(hashfunc)tuplehash, /* 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 */
tuple_doc, /* tp_doc */
(traverseproc)tupletraverse, /* tp_traverse */
0, /* tp_clear */
tuplerichcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* 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 */
tuple_new, /* tp_new */
_PyObject_GC_Del, /* tp_free */
};
/* The following function breaks the notion that tuples are immutable:
it changes the size of a tuple. We get away with this only if there
is only one module referencing the object. You can also think of it
as creating a new tuple object and destroying the old one, only more
efficiently. In any case, don't use this if the tuple may already be
known to some other part of the code. */
DL_EXPORT(int)
_PyTuple_Resize(PyObject **pv, int newsize)
{
register PyTupleObject *v;
register PyTupleObject *sv;
int i;
int oldsize;
v = (PyTupleObject *) *pv;
if (v == NULL || v->ob_type != &PyTuple_Type ||
(v->ob_size != 0 && v->ob_refcnt != 1)) {
*pv = 0;
Py_XDECREF(v);
PyErr_BadInternalCall();
return -1;
}
oldsize = v->ob_size;
if (oldsize == newsize)
return 0;
if (oldsize == 0) {
/* Empty tuples are often shared, so we should never
resize them in-place even if we do own the only
(current) reference */
Py_DECREF(v);
*pv = PyTuple_New(newsize);
return *pv == NULL ? -1 : 0;
}
/* XXX UNREF/NEWREF interface should be more symmetrical */
#ifdef Py_REF_DEBUG
--_Py_RefTotal;
#endif
_PyObject_GC_UNTRACK(v);
_Py_ForgetReference((PyObject *) v);
/* DECREF items deleted by shrinkage */
for (i = newsize; i < oldsize; i++) {
Py_XDECREF(v->ob_item[i]);
v->ob_item[i] = NULL;
}
sv = PyObject_GC_Resize(PyTupleObject, v, newsize);
if (sv == NULL) {
*pv = NULL;
PyObject_GC_Del(v);
return -1;
}
_Py_NewReference((PyObject *) sv);
/* Zero out items added by growing */
for (i = oldsize; i < newsize; i++)
sv->ob_item[i] = NULL;
*pv = (PyObject *) sv;
_PyObject_GC_TRACK(sv);
return 0;
}
DL_EXPORT(void)
PyTuple_Fini(void)
{
#if MAXSAVESIZE > 0
int i;
#ifdef SYMBIAN
SPy_Python_globals* pyglobals = PYTHON_GLOBALS; // avoid TLS reads
#endif
Py_XDECREF(free_tuples[0]);
free_tuples[0] = NULL;
for (i = 1; i < MAXSAVESIZE; i++) {
PyTupleObject *p, *q;
p = free_tuples[i];
free_tuples[i] = NULL;
while (p) {
q = p;
p = (PyTupleObject *)(p->ob_item[0]);
PyObject_GC_Del(q);
}
}
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -