Python系列 60 属性代理

属性代理

属性代理是指通过@property描述符装饰器来规定用户对类或者实例中某一属性的操作做出行为限制的方式。

类似于JavaScript中的代理器,Vue中的计算属性等,Python中则称之为描述符。

计算获取

BMI指数是用来衡量一个人的体重与身高对健康影响的一个指标,计算公式为:

BMI指数计算公式: BMI = 体重(kg) / (身高m**2)

BMI正常值在20至25之间,超过25为超重,30以上则属肥胖

身高或体重是不断变化的,因而每次想查看BMI值都需要通过计算才能得到,但很明显BMI听起来更像是一个特征而非功能。

为此Python专门提供了一个装饰器@property,可以将类中的方法伪装成属性,对象在访问该特殊属性时会触发功能的执行,然后将返回值作为本次访问的结果,例如:

class Person:
    def __init__(self, name, height, weight):
        self.name = name
        self.height = height
        self.weight = weight

    @property
    def bmi(self):
        v = self.weight / (self.height ** 2)
        if 20 < v < 25:
            return "normal"
        if v > 25:
            return "overweight"
        return "obesity"


if __name__ == "__main__":
    instanceObject = Person("ken", height=1.76, weight=77)
    # autoRun instanceObjectMethod => bmi(self=instanceObject)
    print(instanceObject.bmi)

# normal

行为控制

你也可以使用其他的形式,来控制属性的删改查等行为,如下所示:

class Person:
    def __init__(self):
        self.__attr = None

    @property
    def name(self):
        """获取name时自动触发该方法,只有当__attr不为None才能被获取到"""
        if not self.__attr is None:
            return self.__attr
        else:
            raise AttributeError("name is not set")

    @name.setter
    def name(self, params):
        """设置name时自动触发该方法,只有当params为 'Jack' 时才能成功为__attr赋值"""
        if params != "Jack":
            raise AttributeError("name must setting is string 'Jack', but you set is %s"%params)
        else:
            self.__attr = params

    @name.deleter
    def name(self):
        """删除name时自动触发该方法,不允许删除name"""
        raise AttributeError("name not should delete")

if __name__ == "__main__":
   instanceObject = Person()

   instanceObject.name = "Jack"
   print(instanceObject.name)
   del instanceObject.name

# Jack
# AttributeError: name not should delete

行为控制

行为控制还有另外一种形式,它是固定的用法,如下所示,效果和上面一样:

class Person:
    def __init__(self):
        self.__attr = None

    def nameGet(self):
        """获取name时自动触发该方法,只有当__attr不为None才能被获取到"""
        if not self.__attr is None:
            return self.__attr
        else:
            raise AttributeError("name is not set")

    def nameSet(self, params):
        """设置name时自动触发该方法,只有当params为 'Jack' 时才能成功为__attr赋值"""
        if params != "Jack":
            raise AttributeError("name must setting is string 'Jack', but you set is %s"%params)
        else:
            self.__attr = params

    def nameDelete(self):
        """删除name时自动触发该方法,不允许删除name"""
        raise AttributeError("name not should delete")

    name = property(fget=nameGet, fset=nameSet, fdel=nameDelete)

if __name__ == "__main__":
   instanceObject = Person()

   instanceObject.name = "Jack"
   print(instanceObject.name)
   del instanceObject.name

# Jack
# AttributeError: name not should delete
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值