简体   繁体   English

从对象类型.__ setattr__有多么不同.__ setattr__?

[英]How different is type.__setattr__ from object.__setattr__?

type.__setattr__ is used for classes, basically instances of metaclasses. type.__setattr__用于类,基本上是元类的实例。 object.__setattr__ on the other hand, is used for instances of classes. 另一方面, object.__setattr__用于类的实例。 This is totally understood. 这完全可以理解。

I don't see a significant difference between the two method, at least at Python level, I notice the two use the same procedures for attribute assignment, correct me if I'm wrong: 我没有看到这两种方法之间存在显着差异,至少在Python级别,我注意到两者使用相同的属性赋值程序,如果我错了,请纠正我:

Suppose a is an instance of a user-defined class, just a normal class: 假设a是用户定义类的实例,只是一个普通类:

class A:
    pass

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

then ax = .. invokes type(a).__setattr__(...) which performs the following steps: 然后ax = ..调用type(a).__setattr__(...)执行以下步骤:

Note: type(a).__setattr__ will find __setattr__ in object builtin class 注意: type(a).__setattr__将在object内置类中找到__setattr__

1) Look for a data descriptor in type(a).__mro__ . 1)在type(a).__mro__查找数据描述符。

2) If a data descriptor was found, call its __set__ method and exit. 2)如果找到了数据描述符,则调用其__set__方法并退出。

3) If no data descriptor was found in type(a).__mro__ , then add attribute to a.__dict__ , a.__dict__['x'] = ... 3)如果是在没有发现数据描述符type(a).__mro__ ,然后添加属性到a.__dict__a.__dict__['x'] = ...


With classes--instances of metaclasses, the process is similar: 使用类 - 元类的实例,过程类似:

class A(metaclass=type):
    pass

then: Ax = ... is translated to type(A).__setattr__(...) which performs the following steps: 然后: Ax = ...被转换为type(A).__setattr__(...) ,它执行以下步骤:

Note: type(A).__setattr__ will find __setattr__ in type builtin class 注意: type(A).__setattr__将在type内置类中找到__setattr__

1) Look for a data descriptor in type(A).__mro__ 1)在type(A).__mro__查找数据描述符type(A).__mro__

2) If a data descriptor was found, call its __set__ method and exit. 2)如果找到了数据描述符,则调用其__set__方法并退出。

3) If no data descriptor was found in type(A).__mro__ , then add attribute to A.__dict__ , a.__dict__['x'] = ... 3)如果在type(A).__mro__没有找到数据描述符,则将属性添加到A.__dict__ a.__dict__['x'] = ...a.__dict__['x'] = ...

But object.__setattr__ doesn't work for classes: 但是object.__setattr__不适用于类:

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

and vice versa, type.__setattr__ doesn't work for instances of A : 反之亦然, type.__setattr__不适用于A实例:

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

Hmmm! 嗯! There must be something different between the two methods. 两种方法之间必定存在不同之处。 This is subtle, but true nonetheless! 这很微妙,但仍然是真的!

Presumably the two methods perform the same steps inside __setattr__ , what is the difference between type.__setattr__ and object.__setattr__ so that type.__setattr__ is limited to classes and object.__setattr__ is limited to instances of classes? 据推测,这两个方法在__setattr__执行相同的步骤, type.__setattr__object.__setattr__之间的区别是什么,因此type.__setattr__仅限于类和object.__setattr__仅限于类的实例?

type.__setattr__ has a check to prevent setting attributes on types like int , and it does a bunch of invisible cleanup that isn't needed for normal objects. type.__setattr__有一个检查来阻止像int这样的类型设置属性,它会执行一堆普通对象不需要的隐形清理。


Let's take a look under the hood! 我们来看看引擎盖! Here's type.__setattr__ : 这是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);
}

and if we examine PyBaseObject_Type , we see it uses PyObject_GenericSetAttr for its __setattr__ , the same call that appears halfway through type_setattro . 如果我们检查PyBaseObject_Type ,我们会看到它使用PyObject_GenericSetAttr作为__setattr__ ,这是在type_setattro中途出现的同一个调用。

Thus, type.__setattr__ is like object.__setattr__ , but with some additional handling wrapped around it. 因此, type.__setattr__就像object.__setattr__ ,但有一些额外的处理包裹它。

First, the if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) check prohibits attribute assignment on types written in C, like int or numpy.array , because assigning attributes on those can seriously screw up the Python internals in ways someone unfamiliar with the C API might not expect. 首先, if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE))检查禁止对用C语言编写的类型进行属性赋值,比如intnumpy.array ,因为在那些上分配属性会严重搞砸Python内部,就像有些人不熟悉的那样。 C API可能不会期望。

Second, after the PyObject_GenericSetAttr call updates the type's dict or calls an appropriate descriptor from the metaclass, update_slot fixes up any slots affected by the attribute assignment. 其次,在PyObject_GenericSetAttr调用更新类型的dict或从元类调用适当的描述符之后, update_slot修复受属性赋值影响的任何插槽 These slots are C-level function pointers that implement functionality like instance allocation, in checks, + , deallocation, etc. Most of them have corresponding Python-level methods, like __contains__ or __add__ , and if one of those Python-level methods is reassigned, the corresponding slot (or slots) have to be updated, too. 这些槽是C级函数指针实现的功能像实例分配, in检查, +他们中的大多数对应Python的水平的方法,如,解除分配等等__contains____add__ ,并且如果那些Python的电平的方法之一被重新分配,相应的插槽(或插槽)也必须更新。 update_slot also updates slots on all descendants of the class, and it invalidates entries in an internal attribute cache used for type object attributes. update_slot还会更新类的所有后代上的插槽,并使用于类型对象属性的内部属性高速缓存中的条目无效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用object .__ setattr __(self,…,…)`而不是`setattr(self,…,…)`? - `object.__setattr__(self, …, …)` instead of `setattr(self, …, …)`? setattr(object,name,value)vs object .__ setattr __(name,value) - setattr(object, name, value) vs object.__setattr__(name,value) setattr()和object .__ setattr __()之间有什么区别? - What's the difference between setattr() and object.__setattr__()? 使用object .__ setattr__时发生AttributeError - AttributeError when using object.__setattr__ python 冻结数据类与 object.__setattr__ 不可变 - python frozen dataclass immutable with object.__setattr__ object .__ setattr __()和直接设置之间有什么区别吗? - Is there any difference between object.__setattr__() and directly set? Python 2.7:object .__ setattr__在后台做什么? - Python 2.7: What does object.__setattr__ do under the hood? 为什么只在新样式类中支持object .__ setattr __(self,name,value)? - Why favor object.__setattr__(self, name, value) only in new style classes? 使用setattr()更新对象实例 - Using setattr() to update an object instance Python:如何返回 object 的实例以及使用 setattr 分配的属性 - Python: How to return an instance of an object along with attributes assigned with setattr
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM