Я думал о том, что я считаю более чистым решением для реализации атрибута только для чтения, если это все, что вы хотите.Это вариант решения, которое дал тангентсторм, но полностью исключает необходимость использования метода __getattr__
.
class Foo(object):
def __init__(self):
self.readonly = set()
def set_readonly(self, attr, value):
setattr(self, attr, value)
self.readonly.add(attr)
def __setattr__(self, attr, value):
if hasattr(self, "readonly") and attr in self.readonly:
raise AttributeError("Read only attribute: %s" % (attr,))
object.__setattr__(self, attr, value)
Он работает так:
>>> f = Foo()
>>> f.x = 5
>>> f.set_readonly("y", 9)
>>> f.x, f.y
(5, 9)
>>> f.x = 7
>>> f.y = 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "ro.py", line 13, in __setattr__
raise AttributeError("Read only attribute: %s" % (name,))
AttributeError: Read only attribute: y
Создание только для чтенияСчитать и записать атрибут снова легко:
def unset_readonly(self, attr):
self.readonly.remove(attr)
В моей первой попытке написать эту идею я использовал self.__readonly
вместо self.readonly
, но это приводит к проблеме с установкой атрибута __readonly
, поскольку мне нужно было бы выполнить un-munge атрибут "private", чтобы проверить его наличие (hasattr(self, "_Foo__readonly")
), и это не рекомендуется.