在CPython中如何实现子类方法?

2024-06-16 12:17:11 发布

您现在位置:Python中文网/ 问答频道 /正文

医生说:

Each class keeps a list of weak references to its immediate subclasses. This method returns a list of all those references still alive.

但是每个类如何首先获得对其子类的弱引用的列表呢?换句话说,当我创造

class B(A):
  pass

A如何发现{}只是子类化了它?这种机制是否足够健壮,能够在边缘情况下生存(自定义元类、赋值给__bases__等等)?在


Tags: oftothismethodlistclassreturnsits
1条回答
网友
1楼 · 发布于 2024-06-16 12:17:11

作为新类初始化的一部分,对该类的弱引用被添加到每个基类的tp_subclasses成员中。您可以在^{}中的Python源代码中看到这一点:

int
PyType_Ready(PyTypeObject *type)
{
    ...
    /* Link into each base class's list of subclasses */
    bases = type->tp_bases;
    n = PyTuple_GET_SIZE(bases);
    for (i = 0; i < n; i++) {
        PyObject *b = PyTuple_GET_ITEM(bases, i);
        if (PyType_Check(b) &&
            add_subclass((PyTypeObject *)b, type) < 0)
            goto error;
    }
    ...
}

static int
add_subclass(PyTypeObject *base, PyTypeObject *type)
{
    int result = -1;
    PyObject *dict, *key, *newobj;

    dict = base->tp_subclasses;
    if (dict == NULL) {
        base->tp_subclasses = dict = PyDict_New();
        if (dict == NULL)
            return -1;
    }
    assert(PyDict_CheckExact(dict));
    key = PyLong_FromVoidPtr((void *) type);
    if (key == NULL)
        return -1;
    newobj = PyWeakref_NewRef((PyObject *)type, NULL);
    if (newobj != NULL) {
        result = PyDict_SetItem(dict, key, newobj);
        Py_DECREF(newobj);
    }
    Py_DECREF(key);
    return result;
}

__bases__setter还更新了每个旧基和新基的子类列表:

^{pr2}$

注意,如果一个元类做了一些事情来定制子类关系的含义,__subclasses__不会反映这一点。例如,issubclass(list, collections.abc.Iterable)True,但是list不会出现在从collections.abc.Iterable开始的__subclasses__树的搜索中。在

相关问题 更多 >