首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >type.__setattr__和object.__setattr__有什么不同?

type.__setattr__和object.__setattr__有什么不同?
EN

Stack Overflow用户
提问于 2017-05-02 13:48:49
回答 1查看 1.9K关注 0票数 12

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

我看不出这两个方法之间有什么明显的区别,至少在Python级别上,我注意到这两个方法使用相同的过程进行属性分配,如果我错了,请纠正我:

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

代码语言:javascript
复制
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'] = ...添加属性

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

代码语言:javascript
复制
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__不适用于类:

代码语言:javascript
复制
>>> object.__setattr__(A, 'x', ...)
TypeError: can't apply this __setattr__ to type object

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

代码语言:javascript
复制
>>> type.__setattr__(A(), 'x', ...)
TypeError: descriptor '__setattr__' requires a 'type' object but received a 'A'

嗯!这两种方法之间肯定有些不同。这是微妙的,但还是正确的!

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-05-02 18:45:23

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

让我们看看引擎盖下面!这是type.__setattr__

代码语言:javascript
复制
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 )分配属性,因为在这些类型上分配属性可能会严重破坏Python的内部结构,这是一些不熟悉can的人可能不会想到的。

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

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43739608

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档