Просто создайте свой собственный дескриптор для этого:
class MyDescriptor:
def __set_name__(self, owner, name):
self.name = f'_{name}'
def __get__(self, instance, owner):
return getattr(instance, self.name)
def __set__(self, instance, val):
if val is None:
setattr(instance, self.name, None)
elif val < 0:
setattr(instance, self.name, 0)
else:
setattr(instance, self.name, val)
class Sample:
attr1 = MyDescriptor()
attr2 = MyDescriptor()
attr3 = MyDescriptor()
attr4 = MyDescriptor()
def __init__(self):
self.attr1 = None
self.attr2 = None
self.attr3 = None
self.attr4 = None
Теперь, в действии:
In [3]: s = Sample()
In [4]: s.attr1 = -99
In [5]: s.attr1
Out[5]: 0
In [6]: s.attr2
In [7]: s.attr2 = 10
In [8]: s.attr2
Out[8]: 10
In [9]: s.attr2 = -1
In [10]: s.attr2
Out[10]: 0
См. Дескриптор HOWTO и некоторые другие соответствующие документация
Обратите внимание, я включил возможность None
в логику вашего установщика (ваш код поднял бы TypeError
при инициализации экземпляра, потому что установщик проверяет, если None < 0
),Также обратите внимание, что вы, вероятно, не хотите использовать двойное подчеркивание имен (, что не означает частное ), поэтому я использовал условное одинарное подчеркивание для обозначенияпеременная не является частью публичного API.Использование двойного подчеркивания с искажением имен усложняет ситуацию.