📄 classobject.c
字号:
PyErr_Format(PyExc_AttributeError,
"%.200s instance has no __call__ method",
PyString_AsString(inst->in_class->cl_name));
return NULL;
}
/* We must check and increment the recursion depth here. Scenario:
class A:
pass
A.__call__ = A() # that's right
a = A() # ok
a() # infinite recursion
This bounces between instance_call() and PyObject_Call() without
ever hitting eval_frame() (which has the main recursion check). */
if (tstate->recursion_depth++ > Py_GetRecursionLimit()) {
PyErr_SetString(PyExc_RuntimeError,
"maximum __call__ recursion depth exceeded");
res = NULL;
}
else
res = PyObject_Call(call, arg, kw);
tstate->recursion_depth--;
Py_DECREF(call);
return res;
}
const static PyNumberMethods instance_as_number = {
(binaryfunc)instance_add, /* nb_add */
(binaryfunc)instance_sub, /* nb_subtract */
(binaryfunc)instance_mul, /* nb_multiply */
(binaryfunc)instance_div, /* nb_divide */
(binaryfunc)instance_mod, /* nb_remainder */
(binaryfunc)instance_divmod, /* nb_divmod */
(ternaryfunc)instance_pow, /* nb_power */
(unaryfunc)instance_neg, /* nb_negative */
(unaryfunc)instance_pos, /* nb_positive */
(unaryfunc)instance_abs, /* nb_absolute */
(inquiry)instance_nonzero, /* nb_nonzero */
(unaryfunc)instance_invert, /* nb_invert */
(binaryfunc)instance_lshift, /* nb_lshift */
(binaryfunc)instance_rshift, /* nb_rshift */
(binaryfunc)instance_and, /* nb_and */
(binaryfunc)instance_xor, /* nb_xor */
(binaryfunc)instance_or, /* nb_or */
(coercion)instance_coerce, /* nb_coerce */
(unaryfunc)instance_int, /* nb_int */
(unaryfunc)instance_long, /* nb_long */
(unaryfunc)instance_float, /* nb_float */
(unaryfunc)instance_oct, /* nb_oct */
(unaryfunc)instance_hex, /* nb_hex */
(binaryfunc)instance_iadd, /* nb_inplace_add */
(binaryfunc)instance_isub, /* nb_inplace_subtract */
(binaryfunc)instance_imul, /* nb_inplace_multiply */
(binaryfunc)instance_idiv, /* nb_inplace_divide */
(binaryfunc)instance_imod, /* nb_inplace_remainder */
(ternaryfunc)instance_ipow, /* nb_inplace_power */
(binaryfunc)instance_ilshift, /* nb_inplace_lshift */
(binaryfunc)instance_irshift, /* nb_inplace_rshift */
(binaryfunc)instance_iand, /* nb_inplace_and */
(binaryfunc)instance_ixor, /* nb_inplace_xor */
(binaryfunc)instance_ior, /* nb_inplace_or */
(binaryfunc)instance_floordiv, /* nb_floor_divide */
(binaryfunc)instance_truediv, /* nb_true_divide */
(binaryfunc)instance_ifloordiv, /* nb_inplace_floor_divide */
(binaryfunc)instance_itruediv, /* nb_inplace_true_divide */
};
#ifndef SYMBIAN
PyTypeObject PyInstance_Type = {
PyObject_HEAD_INIT(&PyType_Type)
#else
const PyTypeObject c_PyInstance_Type = {
PyObject_HEAD_INIT(NULL)
#endif
0,
"instance",
sizeof(PyInstanceObject),
0,
(destructor)instance_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
instance_compare, /* tp_compare */
(reprfunc)instance_repr, /* tp_repr */
&instance_as_number, /* tp_as_number */
&instance_as_sequence, /* tp_as_sequence */
&instance_as_mapping, /* tp_as_mapping */
(hashfunc)instance_hash, /* tp_hash */
instance_call, /* tp_call */
(reprfunc)instance_str, /* tp_str */
(getattrofunc)instance_getattr, /* tp_getattro */
(setattrofunc)instance_setattr, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES,/*tp_flags*/
0, /* tp_doc */
(traverseproc)instance_traverse, /* tp_traverse */
0, /* tp_clear */
instance_richcompare, /* tp_richcompare */
offsetof(PyInstanceObject, in_weakreflist), /* tp_weaklistoffset */
(getiterfunc)instance_getiter, /* tp_iter */
(iternextfunc)instance_iternext, /* tp_iternext */
};
/* Instance method objects are used for two purposes:
(a) as bound instance methods (returned by instancename.methodname)
(b) as unbound methods (returned by ClassName.methodname)
In case (b), im_self is NULL
*/
#ifndef SYMBIAN
static PyMethodObject *free_list;
#else
#define free_list (pyglobals->classobj_free_list)
#endif
DL_EXPORT(PyObject *)
PyMethod_New(PyObject *func, PyObject *self, PyObject *class)
{
register PyMethodObject *im;
#ifdef SYMBIAN
SPy_Python_globals* pyglobals = PYTHON_GLOBALS; // avoid TLS reads
#endif
if (!PyCallable_Check(func)) {
PyErr_BadInternalCall();
return NULL;
}
im = free_list;
if (im != NULL) {
free_list = (PyMethodObject *)(im->im_self);
PyObject_INIT(im, &PyMethod_Type);
}
else {
im = PyObject_GC_New(PyMethodObject, &PyMethod_Type);
if (im == NULL)
return NULL;
}
im->im_weakreflist = NULL;
Py_INCREF(func);
im->im_func = func;
Py_XINCREF(self);
im->im_self = self;
Py_XINCREF(class);
im->im_class = class;
_PyObject_GC_TRACK(im);
return (PyObject *)im;
}
/* Descriptors for PyMethod attributes */
/* im_class, im_func and im_self are stored in the PyMethod object */
#define OFF(x) offsetof(PyMethodObject, x)
const static PyMemberDef instancemethod_memberlist[] = {
{"im_class", T_OBJECT, OFF(im_class), READONLY|RESTRICTED,
"the class associated with a method"},
{"im_func", T_OBJECT, OFF(im_func), READONLY|RESTRICTED,
"the function (or other callable) implementing a method"},
{"im_self", T_OBJECT, OFF(im_self), READONLY|RESTRICTED,
"the instance to which a method is bound; None for unbound methods"},
{NULL} /* Sentinel */
};
/* The getattr() implementation for PyMethod objects is similar to
PyObject_GenericGetAttr(), but instead of looking in __dict__ it
asks im_self for the attribute. Then the error handling is a bit
different because we want to preserve the exception raised by the
delegate, unless we have an alternative from our class. */
static PyObject *
instancemethod_getattro(PyObject *obj, PyObject *name)
{
PyMethodObject *im = (PyMethodObject *)obj;
PyTypeObject *tp = obj->ob_type;
PyObject *descr = NULL, *res;
descrgetfunc f = NULL;
if (PyType_HasFeature(tp, Py_TPFLAGS_HAVE_CLASS)) {
if (tp->tp_dict == NULL) {
if (PyType_Ready(tp) < 0)
return NULL;
}
descr = _PyType_Lookup(tp, name);
}
f = NULL;
if (descr != NULL) {
f = TP_DESCR_GET(descr->ob_type);
if (f != NULL && PyDescr_IsData(descr))
return f(descr, obj, (PyObject *)obj->ob_type);
}
res = PyObject_GetAttr(im->im_func, name);
if (res != NULL || !PyErr_ExceptionMatches(PyExc_AttributeError))
return res;
if (f != NULL) {
PyErr_Clear();
return f(descr, obj, (PyObject *)obj->ob_type);
}
if (descr != NULL) {
PyErr_Clear();
Py_INCREF(descr);
return descr;
}
assert(PyErr_Occurred());
return NULL;
}
static void
instancemethod_dealloc(register PyMethodObject *im)
{
#ifdef SYMBIAN
SPy_Python_globals* pyglobals = PYTHON_GLOBALS; // avoid TLS reads
#endif
_PyObject_GC_UNTRACK(im);
if (im->im_weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *)im);
Py_DECREF(im->im_func);
Py_XDECREF(im->im_self);
Py_XDECREF(im->im_class);
im->im_self = (PyObject *)free_list;
free_list = im;
}
static int
instancemethod_compare(PyMethodObject *a, PyMethodObject *b)
{
if (a->im_self != b->im_self)
return (a->im_self < b->im_self) ? -1 : 1;
return PyObject_Compare(a->im_func, b->im_func);
}
static PyObject *
instancemethod_repr(PyMethodObject *a)
{
PyObject *self = a->im_self;
PyObject *func = a->im_func;
PyObject *klass = a->im_class;
PyObject *funcname = NULL, *klassname = NULL, *result = NULL;
char *sfuncname = "?", *sklassname = "?";
funcname = PyObject_GetAttrString(func, "__name__");
if (funcname == NULL)
PyErr_Clear();
else if (!PyString_Check(funcname)) {
Py_DECREF(funcname);
funcname = NULL;
}
else
sfuncname = PyString_AS_STRING(funcname);
if (klass == NULL)
klassname = NULL;
else {
klassname = PyObject_GetAttrString(klass, "__name__");
if (klassname == NULL)
PyErr_Clear();
else if (!PyString_Check(klassname)) {
Py_DECREF(klassname);
klassname = NULL;
}
else
sklassname = PyString_AS_STRING(klassname);
}
if (self == NULL)
result = PyString_FromFormat("<unbound method %s.%s>",
sklassname, sfuncname);
else {
/* XXX Shouldn't use repr() here! */
PyObject *selfrepr = PyObject_Repr(self);
if (selfrepr == NULL)
goto fail;
if (!PyString_Check(selfrepr)) {
Py_DECREF(selfrepr);
goto fail;
}
result = PyString_FromFormat("<bound method %s.%s of %s>",
sklassname, sfuncname,
PyString_AS_STRING(selfrepr));
Py_DECREF(selfrepr);
}
fail:
Py_XDECREF(funcname);
Py_XDECREF(klassname);
return result;
}
static long
instancemethod_hash(PyMethodObject *a)
{
long x, y;
if (a->im_self == NULL)
x = PyObject_Hash(Py_None);
else
x = PyObject_Hash(a->im_self);
if (x == -1)
return -1;
y = PyObject_Hash(a->im_func);
if (y == -1)
return -1;
return x ^ y;
}
static int
instancemethod_traverse(PyMethodObject *im, visitproc visit, void *arg)
{
int err;
if (im->im_func) {
err = visit(im->im_func, arg);
if (err)
return err;
}
if (im->im_self) {
err = visit(im->im_self, arg);
if (err)
return err;
}
if (im->im_class) {
err = visit(im->im_class, arg);
if (err)
return err;
}
return 0;
}
static char *
getclassname(PyObject *class)
{
PyObject *name;
if (class == NULL)
name = NULL;
else
name = PyObject_GetAttrString(class, "__name__");
if (name == NULL) {
PyErr_Clear();
return "?";
}
if (!PyString_Check(name)) {
Py_DECREF(name);
return "?";
}
PyString_InternInPlace(&name);
Py_DECREF(name);
return PyString_AS_STRING(name);
}
static char *
getinstclassname(PyObject *inst)
{
PyObject *class;
char *name;
if (inst == NULL)
return "nothing";
class = PyObject_GetAttrString(inst, "__class__");
if (class == NULL) {
PyErr_Clear();
class = (PyObject *)(inst->ob_type);
Py_INCREF(class);
}
name = getclassname(class);
Py_XDECREF(class);
return name;
}
static PyObject *
instancemethod_call(PyObject *func, PyObject *arg, PyObject *kw)
{
PyObject *self = PyMethod_GET_SELF(func);
PyObject *class = PyMethod_GET_CLASS(func);
PyObject *result;
func = PyMethod_GET_FUNCTION(func);
if (self == NULL) {
/* Unbound methods must be called with an instance of
the class (or a derived class) as first argument */
int ok;
if (PyTuple_Size(arg) >= 1)
self = PyTuple_GET_ITEM(arg, 0);
if (self == NULL)
ok = 0;
else {
ok = PyObject_IsInstance(self, class);
if (ok < 0)
return NULL;
}
if (!ok) {
PyErr_Format(PyExc_TypeError,
"unbound method %s%s must be called with "
"%s instance as first argument "
"(got %s%s instead)",
PyEval_GetFuncName(func),
PyEval_GetFuncDesc(func),
getclassname(class),
getinstclassname(self),
self == NULL ? "" : " instance");
return NULL;
}
Py_INCREF(arg);
}
else {
int argcount = PyTuple_Size(arg);
PyObject *newarg = PyTuple_New(argcount + 1);
int i;
if (newarg == NULL)
return NULL;
Py_INCREF(self);
PyTuple_SET_ITEM(newarg, 0, self);
for (i = 0; i < argcount; i++) {
PyObject *v = PyTuple_GET_ITEM(arg, i);
Py_XINCREF(v);
PyTuple_SET_ITEM(newarg, i+1, v);
}
arg = newarg;
}
result = PyObject_Call((PyObject *)func, arg, kw);
Py_DECREF(arg);
return result;
}
static PyObject *
instancemethod_descr_get(PyObject *meth, PyObject *obj, PyObject *class)
{
/* Don't rebind an already bound method, or an unbound method
of a class that's not a base class of class */
if (PyMethod_GET_SELF(meth) != NULL ||
(PyMethod_GET_CLASS(meth) != NULL &&
!PyObject_IsSubclass(class, PyMethod_GET_CLASS(meth)))) {
Py_INCREF(meth);
return meth;
}
if (obj == Py_None)
obj = NULL;
return PyMethod_New(PyMethod_GET_FUNCTION(meth), obj, class);
}
#ifndef SYMBIAN
PyTypeObject PyMethod_Type = {
PyObject_HEAD_INIT(&PyType_Type)
#else
const PyTypeObject c_PyMethod_Type = {
PyObject_HEAD_INIT(NULL)
#endif
0,
"instance method",
sizeof(PyMethodObject),
0,
(destructor)instancemethod_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
(cmpfunc)instancemethod_compare, /* tp_compare */
(reprfunc)instancemethod_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
(hashfunc)instancemethod_hash, /* tp_hash */
instancemethod_call, /* tp_call */
0, /* tp_str */
(getattrofunc)instancemethod_getattro, /* tp_getattro */
PyObject_GenericSetAttr, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
0, /* tp_doc */
(traverseproc)instancemethod_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
offsetof(PyMethodObject, im_weakreflist), /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
instancemethod_memberlist, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
instancemethod_descr_get, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
};
/* Clear out the free list */
DL_EXPORT(void)
PyMethod_Fini(void)
{
#ifdef SYMBIAN
SPy_Python_globals* pyglobals = PYTHON_GLOBALS; // avoid TLS reads
#endif
while (free_list) {
PyMethodObject *im = free_list;
free_list = (PyMethodObject *)(im->im_self);
PyObject_GC_Del(im);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -