在 Python 中,如果类型的属性是没有方法的数据描述符,那么在属性更新object.__setattr__
期间引发并type.__setattr__
引发的基本原理是什么?同样,如果类型的属性是没有方法的数据描述符,那么在属性删除期间引发和引发的基本原理是什么?AttributeError
__set__
object.__delattr__
type.__delattr__
AttributeError
__delete__
我之所以问这个问题是因为我注意到了这一点,object.__getattribute__
并且如果该类型具有一个属性,该属性是一个没有方法的数据描述符,type.__getattribute__
则不要在属性查找期间引发。AttributeError
__get__
object.__getattribute__
这是一个简单的程序,说明一方面属性查找(AttributeError
未引发)与属性更新object.__setattr__
和属性删除object.__delattr__
另一方面(引发)之间的差异AttributeError
:
class DataDescriptor1: # missing __get__
def __set__(self, instance, value): pass
def __delete__(self, instance): pass
class DataDescriptor2: # missing __set__
def __get__(self, instance, owner=None): pass
def __delete__(self, instance): pass
class DataDescriptor3: # missing __delete__
def __get__(self, instance, owner=None): pass
def __set__(self, instance, value): pass
class A:
x = DataDescriptor1()
y = DataDescriptor2()
z = DataDescriptor3()
a = A()
vars(a).update({'x': 'foo', 'y': 'bar', 'z': 'baz'})
a.x
# actual: returns 'foo'
# expected: returns 'foo'
a.y = 'qux'
# actual: raises AttributeError: __set__
# expected: vars(a)['y'] == 'qux'
del a.z
# actual: raises AttributeError: __delete__
# expected: 'z' not in vars(a)
type.__getattribute__
这是另一个简单的程序,说明一方面属性查找(AttributeError
未引发)与另一方面属性更新和type.__setattr__
属性删除(引发)之间的差异:type.__delattr__
AttributeError
class DataDescriptor1: # missing __get__
def __set__(self, instance, value): pass
def __delete__(self, instance): pass
class DataDescriptor2: # missing __set__
def __get__(self, instance, owner=None): pass
def __delete__(self, instance): pass
class DataDescriptor3: # missing __delete__
def __get__(self, instance, owner=None): pass
def __set__(self, instance, value): pass
class M(type):
x = DataDescriptor1()
y = DataDescriptor2()
z = DataDescriptor3()
class A(metaclass=M):
x = 'foo'
y = 'bar'
z = 'baz'
A.x
# actual: returns 'foo'
# expected: returns 'foo'
A.y = 'qux'
# actual: raises AttributeError: __set__
# expected: vars(A)['y'] == 'qux'
del A.z
# actual: raises AttributeError: __delete__
# expected: 'z' not in vars(A)
我希望实例字典发生突变,而不是获取AttributeError
属性更新和属性删除。属性查找从实例字典返回一个值,所以我想知道为什么属性更新和属性删除也不使用实例字典(如果类型没有作为数据描述符的属性,他们会这样做)。