【发布时间】:2021-06-19 13:43:10
【问题描述】:
在 Python 中,如果类型有一个属性是 data 没有__set__ 方法的描述符?同样,如果类型的属性是 data 描述符而没有__delete__方法?
我之所以问这个问题是因为我注意到 object.__getattribute__ 和 type.__getattribute__ 在属性 lookup 期间确实不会引发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 用于属性更新和属性删除。属性查找从实例字典返回一个值,所以我想知道为什么属性更新和属性删除也不使用实例字典(就像如果类型没有作为数据描述符的属性时他们会这样做)。
【问题讨论】:
标签: python attributes lookup python-descriptors python-datamodel