如何创建只读插槽?

to94eoyn  于 2021-07-14  发布在  Java
关注(0)|答案(1)|浏览(377)

默认情况下,插槽是可写的:

>>> class A: __slots__ = ('x',)
... 
>>> list(vars(A))
['__module__', '__slots__', 'x', '__doc__']
>>> vars(A)['x']
<member 'x' of 'A' objects>
>>> a = A()
>>> a.x = 'foo'
>>> del a.x

如何创建只读插槽,如插槽 '__thisclass__' , '__self__' ,和 '__self_class__' 全班同学 super ?

>>> list(vars(super))
['__repr__', '__getattribute__', '__get__', '__init__', '__new__',
 '__thisclass__', '__self__', '__self_class__', '__doc__']
>>> vars(super)['__thisclass__']
<member '__thisclass__' of 'super' objects>
>>> s = super(int, 123)
>>> s.__thisclass__ = float
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: readonly attribute
>>> del s.__thisclass__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: readonly attribute
jm81lzqq

jm81lzqq1#

不能,python代码中没有选项来创建只读描述符,比如 __thisclass__ 等等。
在c api中,所有的插槽都使用相同的描述符对象类型,对于 PyMemberDef 具有 flags 设置为 READONLY .
e、 g super 您标识的描述符在 super_members 数组:

static PyMemberDef super_members[] = {
    {"__thisclass__", T_OBJECT, offsetof(superobject, type), READONLY,
     "the class invoking super()"},
    {"__self__",  T_OBJECT, offsetof(superobject, obj), READONLY,
     "the instance invoking super(); may be None"},
    {"__self_class__", T_OBJECT, offsetof(superobject, obj_type), READONLY,
     "the type of the instance invoking super(); may be None"},
    {0}
};

什么时候 __slots__ 正在处理,没有可以设置此标志的路径;中的代码 type.__new__ 只需设置前三个值,即 name , type 以及 offset ,分别是:

mp = PyHeapType_GET_MEMBERS(et);
    slotoffset = base->tp_basicsize;
    if (et->ht_slots != NULL) {
        for (i = 0; i < nslots; i++, mp++) {
            mp->name = PyUnicode_AsUTF8(
                PyTuple_GET_ITEM(et->ht_slots, i));
            if (mp->name == NULL)
                goto error;
            mp->type = T_OBJECT_EX;
            mp->offset = slotoffset;

            /* __dict__ and __weakref__ are already filtered out */
            assert(strcmp(mp->name, "__dict__") != 0);
            assert(strcmp(mp->name, "__weakref__") != 0);

            slotoffset += sizeof(PyObject *);
        }
    }

供参考: PyHeapType_GET_MEMBERS 访问 PyMemberDef 正在创建的新类型对象的数组。它已经分配了正确数量的插槽。 et->ht_slots 是插槽名称的元组。 slotoffset 是示例对象内存区域中存储插槽内容的相对偏移量。
这个 T_OBJECT_EX 的值 type 字段表示插槽存储指向python对象的指针,如果指针设置为 NULLAttributeError 当您尝试获取值时,会引发。
请注意,如果可以将这些插槽设置为只读,那么在创建新示例之前还需要一种机制来提供它们的值!毕竟,如果阻止所有python代码在示例上设置readonly属性,那么python类将如何设置初始值?

相关问题