Property support for attrs
pip install attr_property
import attr
from attr_property import attr_property, attr_property_class
@attr_property_class
@attr.s
class A:
a = attr_property()
b = attr.ib() # compatible with original attr.ib
def a_getter(this, value):
print('Property a has been accessed!')
return value + 1
def a_setter(this, value):
print(f'Property a has been set with value {value!r}')
def a_deleter(this):
print('Property has been deleted!')
@attr_property_class
@attr.s
class A:
a = attr_property(getter = a_getter, setter = a_setter, deleter = a_deleter)
a = A(a = 1)
# Property a has been set with value 1
# Property a has been accessed!
print('a.a =', a.a)
# a.a = 2
del a.a
# Property has been deleted!
a.a
# Error
@attr_property_class
@attr.s
class A:
a = attr_property(deleter = False)
a = A(1)
del a.a
# AttributeError: can't delete attribute
@attr_property_class
@attr.s
class A:
# remember you can set init = True or
# set any default values for it,
# as setter will be called in __init__
# this will cause AttributeError
a = attr_property(init = False, setter = False, getter = lambda this, value: 2)
a = A()
a.a = 1
# AttributeError: can't set attribute
# OK to call getter
a.a == 2
@attr_property_class
@attr.s
class A:
a = attr_property(converter = int, validator_runtime = True, converter_runtime = True)
@a.validator
def lessthan20(self, attribute, value):
if value >= 20:
raise ValueError("d should be less than 20.")
a = A('3')
# a.a == 3
a.a = '30'
# ValueError
Order of execution of setter:
- Delete cached value
- Run converter
- Run validator
- Run specified setter
- Save value as raw value
@attr_property_class
@attr.s
class A:
a = attr_property(getter = lambda this, value: value + 1, cache = True)
a = A(1)
# a.a == 2
# will not do value + again
# validators and converters will be skipped, as well.
@attr_property_class
@attr.s
class A:
a = attr_property(getter = lambda this, value: value + 1, convert = int, raw = True)
a = A('1')
# a.a == 2
# a._a == 1 # converted value
a._a = 9
# AttributeError, it's readonly
Using a different prefix
@attr_property_class
@attr.s
class A:
a = attr_property(getter = lambda this, value: value + 1, convert = int, raw = 'raw_')
a = A('1')
# a.raw_a == 1
- Hack attrs'
_attrs_to_init_script
function to insert codes to initiateself.__attrs_property_raw__
to save raw values and__attrs_property_cached__
to save cached values. - Create
property
s for each attribute in class decoratorattr_property_class
.