Для свойств только для чтения я использую декоратор, иначе я обычно делаю что-то вроде этого:
class Bla(object):
def sneaky():
def fget(self):
return self._sneaky
def fset(self, value):
self._sneaky = value
return locals()
sneaky = property(**sneaky())
Обновление:
В последних версиях python улучшен подход декоратора:
class Bla(object):
@property
def elegant(self):
return self._elegant
@elegant.setter
def elegant(self, value):
self._elegant = value