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)

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM