Python 2.7:object.__setattr__ 在幕后做了什么?

Nin*_*non 2 python attributes class python-2.7 python-internals

在 Python 2.7 中,我可以声明一个新样式的类并使用object.__setattr__以下方法设置一个属性:

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

A().foo # 'bar'
Run Code Online (Sandbox Code Playgroud)

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

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

B().foo
Run Code Online (Sandbox Code Playgroud)

类型错误:不能将此 __setattr__ 应用到实例对象

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

当我调用object.__setattr__旧式类无法实现的新式类时,幕后发生了什么?

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

Mar*_*ers 6

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

检查是为了防止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"
Run Code Online (Sandbox Code Playgroud)

请参阅hackcheck()函数和原始 Python-dev 讨论。

旧式实例对象未通过测试只是副作用。

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