Python廖雪峯教程學習筆記:Day11

前言

養成一個好的習慣只需要堅持21天,Day11
這兩天主要學習一下面向對象的高級編程。

使用__slots__

由之前學習類的定義和實例的創建,我們可以給實例綁定不同的屬性,例如:

class Student(object):
	pass
s = Student()
s.name = 'Tom' # 動態給實例綁定一個屬性
print(s.name)
# Tom

如果我們只允許對Student實例添加name和age屬性,達到限制的目的,我們就可以定義一個特殊的__solts__變量,來限制該class實例能添加的屬性,接下來Student實例就只能添加name和age屬性了:

class Student(object):
	__solts__ = ('name','age') #用tuple定義允許綁定的屬性名稱

接着進行測試:

s = Student() #創建新的實例
s.name = 'Tom'  # 綁定name屬性
s.age = 23      # 綁定age屬性
s.score = 90    # 綁定score屬性
# Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
# AttributeError: 'Student' object has no attribute 'score'

由於score屬性沒有被放到__solts__中,所以不能綁定score屬性;如果強行綁定就會得到AttributeError錯誤。不過__slots__定義的屬性僅對當前類實例起作用,對繼承的子類是不起作用的。例如GraduateStudent子類是可以綁定score屬性的:

class GraduateStudent(Student):
	paa
g = GraduateStudent()
g.score = 999
print(g.score)
# 90
@property

在綁定屬性的時候,我們需要對參數進行檢查,比如上面在爲對象的score屬性賦值999時,顯然是不符合我們生活中的分數的。爲了限制score的範圍,可以通過設置方法來獲取和設置成績,比如set_score()get_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

如上定義後,就不能對score隨意設值了。當賦予score的值不是int類型或者超過0-100時就會報錯:

s = Student()
s.set_score(90)
print(s.get_score)
# 90
s.set_score(999)
# Traceback (most recent call last):
  ...
# 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

把一個getter方法變成屬性,只需要加上@property。此時,@property本身又創建了另一個裝飾器@score.setter,負責把一個setter方法變成屬性賦值,於是,我們就擁有一個可控的屬性操作:

s = Student()
s.set_score(90)
print(s.score)
# 90
s.set_score(999)
# Traceback (most recent call last):
  ...
# ValueError: score must between 0 ~ 100!

下面的例子中birth是可讀寫屬性,而age就是一個只讀屬性,因爲age可以根據birth和當前時間計算出來。

class Student(object):

    @property
    def birth(self):
        return self._birth

    @birth.setter
    def birth(self, value):
        self._birth = value

    @property
    def age(self):
        return 2015 - self._birth

練習
請利用@property給一個Screen對象加上width和height屬性,以及一個只讀屬性resolution:

class Screen(object):

    @property
    def width(self):
        return self._width
    @width.setter
    def width(self,value):
        if not isinstance(value,int):
            raise ValueError('width must be integer')
        if value < 0:
            raise ValueError('width must be above 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 integer')
        if value < 0:
            raise ValueError('height must be above 0')
        self._height = value

    @property
    def resolution(self):
        return self.width * self.height
# 測試:
s = Screen()
s.width = 1024
s.height = 768
print('resolution =', s.resolution)
if s.resolution == 786432:
    print('測試通過!')
else:
    print('測試失敗!')
# resolution = 786432
# 測試通過!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章