gpt4 book ai didi

python - type.__setattr__ 与 object.__setattr__ 有何不同?

转载 作者:太空狗 更新时间:2023-10-29 20:23:47 26 4
gpt4 key购买 nike

type.__setattr__ 用于类,基本上是元类的实例。另一方面,object.__setattr__ 用于类的实例。这是完全明白的。

我看不出这两种方法有什么显着差异,至少在 Python 级别,我注意到这两种方法使用相同的过程来分配属性,如果我错了请纠正我:

假设 a 是一个用户定义类的实例,只是一个普通类:

class A:
pass

a = A()
a.x = ...

然后 a.x = .. 调用 type(a).__setattr__(...) 执行以下步骤:

注意:type(a).__setattr__ 将在 object 内置类中找到 __setattr__

1) 在type(a).__mro__ 中查找数据描述符。

2) 如果找到数据描述符,则调用其__set__ 方法并退出。

3) 如果在type(a).__mro__中没有找到数据描述符,则将属性添加到a.__dict__, a.__dict__['x '] = ...


对于类——元类的实例,过程类似:

class A(metaclass=type):
pass

然后:A.x = ... 被转换为 type(A).__setattr__(...) 执行以下步骤:

注意:type(A).__setattr__ 将在 type 内置类中找到 __setattr__

1) 在type(A).__mro__

中查找数据描述符

2) 如果找到数据描述符,则调用其__set__ 方法并退出。

3) 如果在type(A).__mro__中没有找到数据描述符,则将属性添加到A.__dict__, a.__dict__['x '] = ...

但是 object.__setattr__ 不适用于类:

>>> object.__setattr__(A, 'x', ...)
TypeError: can't apply this __setattr__ to type object

反之亦然,type.__setattr__ 不适用于 A 的实例:

>>> type.__setattr__(A(), 'x', ...)
TypeError: descriptor '__setattr__' requires a 'type' object but received a 'A'

嗯!这两种方法之间一定有什么不同。这是微妙的,但仍然是真实的!

推测这两种方法在__setattr__ 中执行相同的步骤,type.__setattr__object.__setattr__ 之间有什么区别以便type.__setattr__ 仅限于类而 object.__setattr__ 仅限于类的实例?

最佳答案

type.__setattr__ 有一个检查以防止在 int 等类型上设置属性,并且它做了一堆普通对象不需要的不可见清理。


让我们深入了解一下!这是 type.__setattr__ :

static int
type_setattro(PyTypeObject *type, PyObject *name, PyObject *value)
{
if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
PyErr_Format(
PyExc_TypeError,
"can't set attributes of built-in/extension type '%s'",
type->tp_name);
return -1;
}
if (PyObject_GenericSetAttr((PyObject *)type, name, value) < 0)
return -1;
return update_slot(type, name);
}

如果我们检查 PyBaseObject_Type ,我们看到它使用 PyObject_GenericSetAttr 作为其 __setattr__,与 type_setattro 中途出现的相同调用。

因此,type.__setattr__ 类似于 object.__setattr__,但围绕它进行了一些额外的处理。

首先,if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) 检查禁止对用 C 编写的类型进行属性分配,例如 intnumpy。 array,因为在这些上分配属性可能会以不熟悉 C API 的人可能不会预料到的方式严重搞砸 Python 内部结构。

其次,在 PyObject_GenericSetAttr 调用更新类型的字典或从元类中调用适当的描述符后,update_slot 修复受以下影响的所有插槽属性赋值。这些槽是 C 级函数指针,实现实例分配、in 检查、+、释放等功能。它们中的大多数都有相应的 Python 级方法,如 __contains____add__,如果其中一个 Python 级方法被重新分配,相应的槽(或槽)也必须更新。 update_slot 还更新类的所有后代上的槽,并使用于类型对象属性的内部属性缓存中的条目无效。

关于python - type.__setattr__ 与 object.__setattr__ 有何不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43739608/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com