@propetry的作用就是让一个方法可以当成属性被调用。
@property的实现比较复杂,我们先考察如何使用。把一个getter方法变成属性,只需要加上@property就可以了,此时,@property本身又创建了另一个装饰器@score.setter,负责把一个setter方法变成属性赋值,于是,我们就拥有一个可控的属性操作
class Rectangle():
@property
def width(self):
return self._width
@width.setter
def width(self, value):
if not isinstance(value,int):
raise ValueError('be int!')
if value < 0 or value > 100:
raise ValueError('valueError')
self._width = value
@property
def squer(self):
return self._width * self._width
s = Rectangle()
s.width = 20 #width这个属性是可读可写的,写入时还会检查
print(s.squer) #squer这个属性时只读的,无法写入,会报错。
一个例子:
# 使用@property装饰器,data会被self.data这个属性调用,返回_data
# 这样可以对参数进行检查
@property
def data(self):
# is_valid会把initial_data替换为_validated_data
# 这个if防止没有调用is_valid
if hasattr(self, 'initial_data') and not hasattr(self, '_validated_data'):
msg = (
'When a serializer is passed a `data` keyword argument you '
'must call `.is_valid()` before attempting to access the '
'serialized `.data` representation.\n'
'You should either call `.is_valid()` first, '
'or access `.initial_data` instead.'
)
raise AssertionError(msg)
# 设定返回值_data
if not hasattr(self, '_data'):
if self.instance is not None and not getattr(self, '_errors', None):
self._data = self.to_representation(self.instance)
elif hasattr(self, '_validated_data') and not getattr(self, '_errors', None):
self._data = self.to_representation(self.validated_data)
else:
self._data = self.get_initial()
return self._data
# 参数检查:没有_errors,则self.errors调用就会出错
@property
def errors(self):
if not hasattr(self, '_errors'):
msg = 'You must call `.is_valid()` before accessing `.errors`.'
raise AssertionError(msg)
return self._errors
# 参数检查:没有_validated_data,则self.validated_data调用就会出错
@property
def validated_data(self):
if not hasattr(self, '_validated_data'):
msg = 'You must call `.is_valid()` before accessing `.validated_data`.'
raise AssertionError(msg)
return self._validated_data