zoukankan      html  css  js  c++  java
  • Python3之使用@property

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

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

      这显然不会逻辑,为了现在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
    

      现在,对人员的Student实例进行操,就不能随心所欲地设置score了

    >>> s.set_score(100)
    >>> s.get_score()
    100
    >>> s.set_score(101)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 8, in set_score
    ValueError: score must between 0~100!
    

      但是,上面的调用方法比较复杂,有没有直接用属性这么直接减掉

      有没有既能检查参数,又可以有类似属性这样的简单方式来访问类的变量呢。对于类的方法,装饰器一样起作用。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
    

      @property的实现比较复杂,这里看如何使用。把一个getter的方法变成属性,只需要加上@property就可以了,此时,@property本身又创建了另一个装饰器,负责把一个setter方法变成属性赋值,于是我们就拥有了一个可控的属性操作:

    >>> s=Student()
    >>> s.score=100
    >>> s.score
    100
    >>> s.score=101
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 18, in score
    ValueError: score must between 0~100!
    

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

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

    class Student(object):
    #出生年格式为2001
      @property
      def birth(self):
        return self._birth
      @birth.setter
      def birth(self,value):
        self._birth=value
    #年龄age定义为只读即没有setter属性
      @property
      def age(self):
        return 2019-self._birth
    

      操作

    >>> s=Student()
    >>> s.birth=2000
    #age是根据birth用2019-birth计算出来的
    >>> s.age
    19
    #直接修改age因为没有定义setter使用报错
    >>> s.age=20
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: can't set attribute
    

      练习

      利用@property给一个Screen对手加上width和heigth属性,已经一个只读属性resolution  Screen.py

    class Screen(object):
        #设置长
        @property
        def width(self):
            return self._width
        #检查输入是否规范必须是int并且大于0
        @width.setter
        def width(self,value):
            if not isinstance(value,int):
                raise ValueError('width must be an integer!')
            if value < 0:
                raise ValueError('width must > 0')
            self._width=value
        #设置高
        @property
        def height(self):
            return self._height
        @height.setter
        def height(self,value):
            if not isinstance(value,int):
                raise ValueError('height must be an integer!')
            if value < 0:
                raise ValueError('height must > 0')
            self._height=value
        #面积只设置getter方法通过长乘高得到
        @property
        def resolution(self):
            return self._width*self._height
    
    s=Screen()
    s.width=1024
    s.height=768
    print(s.resolution)
    

      

  • 相关阅读:
    Jira-dashboard
    SCQA 结构化表达案例:让开场白、讲故事精彩的结构
    outlook 2016 系列1--自动回复
    outlook 2016 系列1--如何将同一回复主题的邮件放在一起
    C++ 成员限定符
    TCP/IP 协议分层
    TCP之拥塞控制
    TCP之流量控制
    TCP之滑动窗口
    TCP中的定时器
  • 原文地址:https://www.cnblogs.com/minseo/p/11100993.html
Copyright © 2011-2022 走看看