zoukankan      html  css  js  c++  java
  • Python面向对象高级编程-@property

    使用@property

    在绑定属性时,如果直接把属性暴露出去,虽然写起来简单,但是没法检查参数,导致可以把成绩随便改:

    >>> class Student(object):
        pass
    
    >>> s =Student()
    >>> s.score=999
    >>> s.score
    999

    这显然不符合逻辑,为了限制score的范围,可以通过一个set_score()方法来设置成绩,再通过一个get_score()来获取成绩,这样,在set_score()方法里,就可以检查参数:

    >>> class Student(object):
        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
    
    >>> s = Student()
    >>> s.set_score('a')
    
    Traceback (most recent call last):
      File "<pyshell#57>", line 1, in <module>
        s.set_score('a')
      File "<pyshell#54>", line 6, in set_score
        raise ValueError("score must be an integer")
    ValueError: score must be an integer
    >>> s.set_score(99999)
    
    Traceback (most recent call last):
      File "<pyshell#58>", line 1, in <module>
        s.set_score(99999)
      File "<pyshell#54>", line 8, in set_score
        raise ValueError("score must between 0~100")
    ValueError: score must between 0~100
    >>> s.set_score(99)
    >>> s.get_score()
    99
    >>> 

    现在,对任意的Student实例进行操作,就不能随心所欲地设置score了:

    但是,上面的调用方法又略显复杂,没有直接用属性这么直接简单。

    有没有技能检查参数,有可以用雷士属性这样简单地方式来访问类的变量?

    记得装饰器(decorator)可以给函数动态加上功能?对于累的方法,装饰器一样起作用,Python内置的@property装饰器就是负责把一个方法变成属性调用的:

    >>> class Student(object):
    
        @property
        def score(self):
            return self._score
    
        @score.setter
        def 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
    
            
    >>> s = Student()
    >>> s.score =99
    >>> s.score = 999
    
    Traceback (most recent call last):
      File "<pyshell#76>", line 1, in <module>
        s.score = 999
      File "<pyshell#73>", line 12, in score
        raise ValueError('score must between 0 ~ 100!')
    ValueError: score must between 0 ~ 100!
    >>> s.score = 'a'
    
    Traceback (most recent call last):
      File "<pyshell#77>", line 1, in <module>
        s.score = 'a'
      File "<pyshell#73>", line 10, in score
        raise ValueError('score must be an integer!')
    ValueError: score must be an integer!
    >>> 

    注意这个@property,在对实例属性操作的时候,就知道该属性很可能不是直接暴露的,而是通过getter和setter方法来实现的。

    还可以定义只读属性,值定义getter方法,不定义setter方法就是一个只读属性:

    >> class Student(object):
        @property
        def birth(self):
            return self._birth
        @birth.setter
        def birth(self,value):
            self._birth = value
        @property
        def age(self):
            return 2017 - self._birth
    
        
    >>> s = Student()
    >>> s.birth = 1995
    
    >>> s.age
    22
    >>> s.age = 23
    
    Traceback (most recent call last):
      File "<pyshell#17>", line 1, in <module>
        s.age = 23
    AttributeError: can't set attribute
    >>> 

    上面的birth是可读写属性,而age就是一个只读属性,因为age可以根据birth和当前时间计算出来。

    总结

    @property广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查,这样程序运行时就减少了出错的可能性。

  • 相关阅读:
    前端开发一些必须知道的相关技术
    页面实现复制功能
    使用localstorage及js模版引擎 开发 m站设想
    jsonp 使用示例
    js 阻止事件冒泡
    html doctype 作用
    localstorage 使用
    跨域技术-jsonp
    mysql实现高效率随机取数据
    mysql主从同步报slave_sql_running:no的解决方案
  • 原文地址:https://www.cnblogs.com/fangpengchengbupter/p/7772134.html
Copyright © 2011-2022 走看看