特性property
当有对属性赋值进行操作的需求时,可以使用property。这可以将一个属性的赋值、获取、删除拆分为3个动作,分别进行不同的实现。
class F1:
@property #获取number属性的方法
def number(self):
return self._number
@number.setter #设置number属性的方法,这里是在设置时对数值减1
def number(self, number):
self._number = number-1
@number.deleter #删除number属性的方法,这里是在删除时个别更改为None
def number(self):
self._number = None
在实现上可以分为两种,主动计算和延迟计算。 在每次更改时(setter和deleter)计算属性值为主动,在get时计算为延迟。这个后面在细说。
使用property在使用上和正常的属性操作没有区别,不过会实现你自己的逻辑。
>> f = F1()
>> f.number = 10
>> f.number
9
特殊方法
实际上property内部是用这些特殊方法实现的。这些特殊方法正常来说是对当前类中所有属性生效的,而property只是对指定的属性
_setattr_
用于创建属性和赋值
_getattr_
用于获取属性值。如果未被定义会抛出AttributeError
_delattr_
用于删除属性
_dir_
返回属性名称列表。注意,方法也是属性,所以返回值中时包含方法名的
主动计算属性
当一个属性更改时,自动计算其他属性值
使用property setter
缺点是如果多个属性需要主动计算,那么需要多个setter
class F1:
@property #获取number属性的方法
def number(self):
return self._number
@number.setter #设置number属性的方法
def number(self, number):
self._number = number-1 #在属性进行更改时进行计算
@number.deleter #删除number属性的方法
def number(self):
self._number = None
重写字典
class F1(dict):
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
self._solve()
# 在设置属性的同时调用计算函数
def __setattr__(self, key, value):
self[key] = value
self._solve()
# 修改get方法,支持点语法
def __getattr__(self, item):
return self.get(item,None)
# 属性名称的列表只返回字典中的键,即实例的属性
def __dir__(self):
return list(self.keys())
# 如果有两个值,那么自动计算第三个值
def _solve(self):
if self.sum is not None and self.first is not None:
self['second'] = self.sum - self.first
elif self.sum is not None and self.second is not None:
self['first'] = self.sum - self.second
elif self.second is not None and self.first is not None:
self['sum'] = self.first + self.second
>> f = F1()
>> f.second = 10
>> f.first = 9
>> print(f)
>> {'second': 10, 'first': 9, 'sum': 19}
>> f.first = 7
>> print(f)
>> {'second': 12, 'first': 7, 'sum': 19}
# 因为判断顺序的原因,在第一次自动计算之后(即三个属性都有值),再次对second赋值无法触发计算
# 因为 sum 和first 都有值, 无法到达第二个elif判断
如果是针对单个属性,那么使用property。而重写字典的形式,一般来说需要搭配限制属性添加来使用。