是类定义中的默认位置吗

是类定义中的默认位置吗

本文介绍了__dict__和__weakref__是类定义中的默认位置吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据 Python语言文档:

所以我想知道这堂课

>>> class A: __slots__ = ('__dict__', '__weakref__')
...
>>> del A.__slots__
>>> vars(A)
mappingproxy({
    '__module__': '__main__',
    '__dict__': <attribute '__dict__' of 'A' objects>,
    '__weakref__': <attribute '__weakref__' of 'A' objects>,
    '__doc__': None
})

与此等效:

>>> class A: pass
...
>>> vars(A)
mappingproxy({
    '__module__': '__main__',
    '__dict__': <attribute '__dict__' of 'A' objects>,
    '__weakref__': <attribute '__weakref__' of 'A' objects>,
    '__doc__': None
})

推荐答案

如果未设置 __ slots __ 属性,则默认设置为创建 __ weakref __ 和 __ dict __ 插槽.

If you don’t set a __slots__ attribute, the default is to create the __weakref__ and __dict__ slots in certain conditions.

这发生在 type .__ new __();为类提供了描述符,以访问每个实例的内存插槽:

This happens in type.__new__(); a class is given descriptors to access memory slots for each instance:

  • 如果基类尚未定义一个( base-&t; tp_dictoffset 为0),则只能有一个 __ dict __ 插槽.
  • 如果基本类型没有定义一个( base-&t; tp_weaklistoffset 为0)并且基本具有固定长度的实例,则只能有一个 __ weakref __ 插槽( base-> tp_itemsize 为0).
  • You can only have a __dict__ slot if the base class doesn’t already define one (base->tp_dictoffset is 0).
  • You can only have a __weakref__ slot if the base type doesn’t define one (base->tp_weaklistoffset is 0) and the base has fixed-length instances (base->tp_itemsize is 0).

然后,如果没有 __ slots __ ,则将标记变量设置为实际启用要添加的插槽.

Then, if there is no __slots__, flag variables are set to actually enable the slots being added.

type .__ new __()实现很长,但是相关部分如下所示:

The type.__new__() implementation is long, but the relevant section looks like this:

    slots = _PyDict_GetItemIdWithError(dict, &PyId___slots__);
    nslots = 0;
    add_dict = 0;
    add_weak = 0;
    may_add_dict = base->tp_dictoffset == 0;
    may_add_weak = base->tp_weaklistoffset == 0 && base->tp_itemsize == 0;
    if (slots == NULL) {
        if (PyErr_Occurred()) {
            goto error;
        }
        if (may_add_dict) {
            add_dict++;
        }
        if (may_add_weak) {
            add_weak++;
        }
    }
    else {
        /* Have slots */
        ...
    }

然后,向下放下约400行,您将找到实际创建插槽的代码:

Then, some 400 lines lower down, you'll find the code that actually creates the slots:

    if (add_dict) {
        if (base->tp_itemsize)
            type->tp_dictoffset = -(long)sizeof(PyObject *);
        else
            type->tp_dictoffset = slotoffset;
        slotoffset += sizeof(PyObject *);
    }
    if (add_weak) {
        assert(!base->tp_itemsize);
        type->tp_weaklistoffset = slotoffset;
        slotoffset += sizeof(PyObject *);
    }

扩展某些本机类型(例如 int bytes )时,您不会获得 __ weakref __ 插槽,因为它们的长度可变实例(由 tp_itemsize 处理).

When extending certain native types (such as int or bytes) you don’t get a __weakref__ slot as they have variable-length instances (handled by tp_itemsize).

这篇关于__dict__和__weakref__是类定义中的默认位置吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-05 10:06