python方法封装成属性-------@property装饰器详解

一、为什么要将方法封装成属性

假设我们定义了一个student类,他有score属性。这样直接把属性暴露出来,不管是修改成绩还是读取成绩都非常方便,但是带来的问题是无法检查参数是否合法(python没有办法强制要求变量类型),导致成绩可以随意修改:

class student():
    def __init__(self,name,score = 0):
        self.name = name
        self.score = score


a = student('wang',20)
print(a.score)   #[OUT]:20

a.score = 999
print(a.score)   #[OUT]:999


a.score = '^_^'
print(a.score)    #[OUT]:'^_^'

初始定义a的成绩为20,但是可以随意修改为999,甚至恶作剧般的将成绩改成字符串,这当然不符合我们设计的初衷。

为了限制score的范围和类型,我们可以通过set_score()方法设置成绩,在通过get_score()方法获取成绩。这样,在set_score()方法里面就可以检查参数:

class student():
   def  __init__(self,name):
        self.name = name
        
   def get_score(self):
         return self._score

   def set_score(self, value):
        if not isinstance(value, int):
            raise ValueError('score must be an integer!')
        if value < 0 or value > 100:
            raise ValueError('score must between 0 ~ 100!')
        self._score = value
        
a = student('wang')


a.set_score(60)
print(a.get_score())    #[OUT]:999


a.set_score(999)    #[OUT]:  ValueError: 'score must between 0 ~ 100!'
print(a.get_score())   

现在就不能随便设置score了,但是上面的操作比较繁琐,没有直接使用属性那么简单。

有没有既能检查参数,又能使用类似属性这样简单的方法来访问类的变量呢。。。。嘿嘿,这就谈到了我们的主题,将方法封装成一个属性。意思就是说,一个东西本质上是个类的方法,但是我们可以把它当做属性来使用。这就是@property的作用了

二、@property如何使用

@property是个装饰器,和普通的装饰器用法相同,直接放在函数定义的上一行就可以了。如下面的例子,在score()函数的定义上面放上@property装饰器,我们就可以像属性一样的使用score了(而不是函数调用)。@property把一个getter方法变成属性,此时,@property本身又创建了另一个装饰器@score.setter,负责把一个setter方法变成属性赋值,于是,我们就拥有一个可控的属性操作。其实同时还会生成一个不常用的装饰器@score.deleter,在进行删除该属性的时候调用。

class student():
   def  __init__(self,name):
        self.name = name
   @property   
   def score(self):
         return self._score
   @score.setter  
   def score(self,value):
         self._score  = value  
   @score.deleter 
   def score(self):
         raise AttributeError("Can't delete attribute")

a = student('wang')
a.score = 10
print(a.score)

     @property有三个相关联的方法,这三个方法的名字都必须一样。 第一个方法是一个 getter 函数,它使得 score 成为一个属性。 其他两个方法给score 属性添加了 setter 和 deleter 函数。 需要强调的是只有在 score 属性被创建后, 后面的两个装饰器 @score.setter 和 @score.deleter 才能被定义。

     property的一个关键特征是它看上去跟普通的attribute没什么两样, 但是访问它的时候会自动触发 getter 、setter 和 deleter 方法。当然getter 、setter 和 deleter 这三个方法不必都实现,通常对于一个只读的属性,只需要定义getter方法就可以,如果允许读和修改,则需要定义getter和setter方法;deleter类似。

三、总结

@property广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查,这样,程序运行时就减少了出错的可能性。对参数的检查放在setter方法中。还可以定义只读属性,只定义getter方法,不定义setter方法就是一个只读属性。

参考资料:

【1】:廖雪峰Python面向对象高级属性

【2】:cookbook-python:创建可管理的属性

猜你喜欢

转载自blog.csdn.net/goodxin_ie/article/details/89441078