On 2/13/22, Christopher Barker <
pyth...@gmail.com> wrote:
>
> Telling newbies that that means that it's either a property with no setter,
> or am object without a __dict__, or one with __slots__ defined is not
> really very helpful.
The __slots__ case is due to the lack of a __dict__ slot. It can be
manually added in __slots__ (though adding __dict__ back is uncommon),
along with the __weakref__ slot.
The exception message when there's no __dict__ is generally good
enough. For example:
>>> (1).x = None
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute 'x'
It's clear that the object has no __dict__ and no descriptor named
"x". However, the message gets confusing with partially implemented
magic attributes.
For example, implement __getattr__(), but not __setattr__() or __delattr__():
class C:
__slots__ = ()
def __getattr__(self, name):
class_name = self.__class__.__name__
if name == 'x':
return 42
raise AttributeError(f'{class_name!r} object has no '
f'attribute {name!r}')
>>> c = C()
>>> c.x
42
>>> c.x = None
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'C' object has no attribute 'x'
Add __setattr__():
def __setattr__(self, name, value):
class_name = self.__class__.__name__
if name == 'x':
raise AttributeError(f'attribute {name!r} of {class_name!r} '
'objects is not writable')
raise AttributeError(f'{class_name!r} object has no '
f'attribute {name!r}')
>>> c = C()
>>> c.x = None
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 12, in __setattr__
AttributeError: attribute 'x' of 'C' objects is not writable
>>> del c.x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'C' object has no attribute 'x'
Add __delattr__():
def __delattr__(self, name):
class_name = self.__class__.__name__
if name == 'x':
raise AttributeError(f'attribute {name!r} of {class_name!r} '
'objects is not writable')
raise AttributeError(f'{class_name!r} object has no '
f'attribute {name!r}')
>>> c = C()
>>> c.x
42
>>> c.x = None
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 12, in __setattr__
AttributeError: attribute 'x' of 'C' objects is not writable
>>> del c.x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 19, in __delattr__
AttributeError: attribute 'x' of 'C' objects is not writable
Message archived at
https://mail.python.org/archives/list/python...@python.org/message/3S2KW3O7O7KKBQD2FVW6NG3CISNHF745/