Author grahamd
Recipients daniel.urban, grahamd, rhettinger
Date 2013-09-30.03:43:31
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1380512611.62.0.933925072888.issue19072@psf.upfronthosting.co.za>
In-reply-to
Content
The classmethod __get__() method does:

static PyObject *
cm_descr_get(PyObject *self, PyObject *obj, PyObject *type)
{
    classmethod *cm = (classmethod *)self;

    if (cm->cm_callable == NULL) {
        PyErr_SetString(PyExc_RuntimeError,
                        "uninitialized classmethod object");
        return NULL;
    }
    if (type == NULL)
        type = (PyObject *)(Py_TYPE(obj));
    return PyMethod_New(cm->cm_callable,
                        type, (PyObject *)(Py_TYPE(type)));
}

So it isn't intentionally calling __call__(). If it still doing binding, but doing it by calling PyMethod_New() rather than using __get__() on the wrapped function. Where it wraps a regular function the result is same as if __get__() was called as __get__() for a regular function internally calls PyMethod_New() in the same way.

static PyObject *
func_descr_get(PyObject *func, PyObject *obj, PyObject *type)
{
    if (obj == Py_None)
        obj = NULL;
    return PyMethod_New(func, obj, type);
}

By not using __get__(), you deny the ability to have chained decorators that want/need the knowledge of the fact that binding was being done. The result for stacking multiple decorators which use regular functions (closures) is exactly the same, but you open up other possibilities of smarter decorators.
History
Date User Action Args
2013-09-30 03:43:31grahamdsetrecipients: + grahamd, rhettinger, daniel.urban
2013-09-30 03:43:31grahamdsetmessageid: <1380512611.62.0.933925072888.issue19072@psf.upfronthosting.co.za>
2013-09-30 03:43:31grahamdlinkissue19072 messages
2013-09-30 03:43:31grahamdcreate