Python3学习(24)--内置装饰器@property

@property


前面我们学过装饰器,我们知道,装饰器的作用就是用来扩展函数的,当然前面我们介绍的装饰器,都是我们自己定义的,格式如下:

@decoretor

def func(*args,**others)

                    pass


func(.....)       #使用装饰过的函数


而我们今天讲的这个装饰器@property,属于Python内置的一个装饰器,广泛应用于类的定义中的,从字面意思上理解,是属性的意思,我们想到了类,类中实例的属性,我们讲过,实例的属性是可以随意绑定的(当然也可以通过__slots__变量限制实例属性的绑定),这就意味着,实例的属性是完全暴露的,这种暴露性,导致属性可以任意被修改,比如下面一个简单的例子:


property.py:


#!/usr/bin/env Python3
# -*- encoding:UTF-8 -*-

class Student(object):
    pass

s = Student()
s.score=90
print(s.score)
s.score=188
print(s.score)

我们给Student类的实例s绑定了一个score属性变量,我们知道,这个变量表示一个学生单科的成绩,当然,据我们所知,成绩应该是不能超过100的(根据满分制100分来),但是,上述的demo我们可以看到,通过实例对象s我们可以随意的修改score的值,哪怕它超过了100分,我们也可以将这个不合理的成绩打印出来:




如果,我们想要控制这种不合理成绩的输出,我们可以在外部绑定属性值的时候,做条件判断,当然,我们也可以在类Student的内部,通过增加两个函数,set_xxx和get_xxx分别来控制属性score的值的输入和返回,因此,我们修改下上述代码:


#!/usr/bin/env Python3
# -*- encoding:UTF-8 -*-

class Student(object):
    def set_score(self,value):
        if value>=0 and value <= 100:
            self.__score = value #还记得__score吗?前面加一个双下划线,表示private私有属性
        else:
            raise ValueError('score must between 0 ~ 100!')
    def get_score(self):
        return self.__score
s = Student()
s.set_score(90)
print(s.get_score())
s.set_score(188)
print(s.get_score())

当我们set成绩等于90的时候,符合类内部定义的函数set_score的条件,当然,设置188的时候,由于超过100了,因此,我们会看到下面的输出:





这样一来,我们就可以到达我们想要的效果,在录入成绩的时候,可以对我们的成绩score的值进行检查判断,从而保证数据的合法性,当然,Python是追求精简的,哪怕少写一对括号,我们的Python也要实现它,这就不得不说我们今天讲的@property了,我们先看下面一段代码:


#!/usr/bin/env Python3
# -*- encoding:UTF-8 -*-

class Student(object):
 
    @property
    def score(self):
        return self.__score    
    @score.setter
    def score(self,value):
        if value>=0 and value <= 100:
            self.__score = value #还记得__score吗?前面加一个双下划线,表示private私有属性
        else:
            raise ValueError('score must between 0 ~ 100!')
    
s = Student()
s.score = 90
print(s.score)


@property 修饰函数score(getter),将score函数变成score属性输出,此外,@property 本身又创建了另一个装饰器@score.setter,负责把一个 setter 函数变成属性赋值,于是,我们虽然看到了类Student内部定义了两个函数score,对,没错,都是score,但是,他们却被不同的装饰器装饰,getter函数被@property修饰,setter函数被@property创建的函数的setter装饰器@score.setter修饰,因此,我们可以直接用s.score=90来代替s.set_socre(90),达到给score属性赋值的效果,简单粗暴,精益求精,虽然实现的效果一样,但是写起来,还是直接s.score=90来的更舒坦一些,我们验证下执行结果:




当然,我们上面创建了@property另一个装饰器函数@xxx.setter,对私有属性__score进行输入值的判断,如果,我们不创建装饰器@xxx.setter可以吗?如果不创建的话,属性xxx就是一个只读属性,意味着不能被修改,下面我们先来看一个普通的只读属性函数:


#!/usr/bin/env Python3
# -*- encoding:UTF-8 -*-

class Student(object):
 
    @property
    def score(self):
        return self.__score    
    @score.setter
    def score(self,value):
        if value>=0 and value <= 100:
            self.__score = value #还记得__score吗?前面加一个双下划线,表示private私有属性
        else:
            raise ValueError('score must between 0 ~ 100!')
    def age(self):
        self.__age = 26
        return self.__age        
s = Student()
s.score = 90
print(s.score)
print(s.age())

我们在类中又定义了一个age 函数,该函数返回一个定值,26,如果我们想要,获得私有属性__age的值26,我们必须调用age()函数:




当然,如果我们直接调用s.age,不会报错,而会输出函数age的函数地址:



通过本篇所学,我们可以给age函数增加一个@property装饰器,达到直接调用s.age输出我们要的26,因此,我们改下上述demo:

#!/usr/bin/env Python3
# -*- encoding:UTF-8 -*-

class Student(object): 
    @property
    def age(self):  #将getter函数转变为属性age直接输出
        self.__age = 26
        return self.__age        
s = Student()
print(s.age)

我们看下输出:





ok,我们的@property发挥奇效,我们说了,我们没有添加@xxx.setter装饰器,因此,age是一个只读属性,如果我们试图修改age的值,我们看下效果,是不是可行?




如果,想要这个age既可以读也可以写,我们可以这样做:





好了,通过本篇的讲解,我们应该知道@property的用途了吧,它可以让调用者写出简短的代码,同时保证对参数进行必要的检查,这样,程序运行时就减少了出错的可能性。














  • 19
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值