Python 2.7: object.__setattr__ 是做什么的?

Python 2.7: What does object.__setattr__ do under the hood?

在 Python 2.7 中,我可以声明新样式 class 并使用 object.__setattr__:

设置属性
class A (object):
    def __init__ (self):
        object.__setattr__(self, 'foo', 'bar')

A().foo # 'bar'

但是,这在旧式中不起作用 class:

class B:
    def __init__ (self):
        object.__setattr__(self, 'foo', 'bar')

B().foo

TypeError: can't apply this __setattr__ to instance object

我知道旧式 classes 不支持这种行为,但我不知道为什么它不起作用。

当我在新式 class 上调用 object.__setattr__ 而旧式 classes 不会发生时,幕后发生了什么?

请注意,我没有将此代码用于任何用途,我只是想了解它。

object.__setattr__ 方法包括一个特定的检查以确保传入的 self 确实是对象(或重用相同 C 函数的另一个对象)的 (subclass)直接地)。该测试不允许传入任何其他内容,包括旧式实例。

检查是为了防止 object.__setattr__ 被用来修改 内置类型 (称为 Carlo Verre hack,以其发现者命名。

没有显式检查(或者如果你编译 Python 禁用它),你可以这样做:

>>> object.__setattr__(str, 'lower', str.upper)
>>> "This is why we can't have nice things".lower()
"THIS IS WHY WE CAN'T HAVE NICE THINGS"

参见hackcheck() function, and the original Python-dev discussion

旧式实例对象没有通过测试只是一个副作用。

请注意,您想要调用 object.__setattr__ 唯一 原因是,如果您有一个实现 __setattr__ 的基础 class ] 你需要绕过的方法。对于旧式实例,您可以改用 self.__dict__[name] = value

类型 - 不是旧式 class,而是所有旧式实例的类型是 types.InstanceType。这种类型是用 C 编写的,并实现了它自己的 __setattr__。 Python 将拒绝将一种 C 类型的 __setattr__ 应用于具有不同 C 级别 __setattr__ 的 C 类型的实例,作为保护 C 数据结构一致性的安全措施。