1. 程式人生 > >再一次重新學習Python——面向物件高階程式設計

再一次重新學習Python——面向物件高階程式設計

給例項繫結一個方法:

>>> def set_age(self, age): # 定義一個函式作為例項方法
...     self.age = age
...
>>> from types import MethodType
>>> s.set_age = MethodType(set_age, s, Student) # 給例項繫結一個方法
>>> s.set_age(25) # 呼叫例項方法
>>> s.age # 測試結果
25

為了給所有例項都繫結方法,可以給class繫結方法:

>>> def set_score(self, score):
...     self.score = score
...
>>> Student.set_score = MethodType(set_score, None, Student)
  •  使用__slots__

用來限制class可以新增的屬性

>>> class Student(object):
...     __slots__ = ('name', 'age') # 用tuple定義允許繫結的屬性名稱
...

 使用__slots__要注意,它定義的屬性只對當前類起作用,對繼承的子類是不起作用的。

除非在子類中也定義__slots__,這樣,子類允許定義的屬性就是自身的__slots__加上父類的__slots__。

  • 使用@property

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
def birth(self):
    return self._birth

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

'''

@property的實現比較複雜,我們先考察如何使用。把一個getter方法變成屬性,只需要加上@property就可以了,此時,@property本身又建立了另一個裝飾器@score.setter,負責把一個setter方法變成屬性賦值,於是,我們就擁有一個可控的屬性操作:

>>> s = Student()
>>> s.score = 60 # OK,實際轉化為s.set_score(60)
>>> s.score # OK,實際轉化為s.get_score()
60
>>> s.score = 9999
Traceback (most recent call last):
  ...
ValueError: score must between 0 ~ 100!
  • 多重繼承 

多重繼承就是繼承多個父類,這樣一個子類就可以同時獲得多個父類的所有功能。

例如

class Dog(Mammal, Runnable):
    pass

Mixin模式

目的是給一個類增加多個功能,在設計類的時候,優先考慮通過多重繼承來組合多個Mixin的功能。

__str__()返回一個好看的字串————改變的是print輸出變數

__repr__()改變的事直接顯示變數呼叫,為除錯服務

__iter__

如果一個類想被用於for...in迴圈,類似list或者tuple那樣,就必須實現一個__iter__()方法,該方法返回一個迭代物件,然後,Python的for迴圈就會不斷呼叫該迭代物件的next()方法拿到迴圈的下一個值,直到遇到StopIteration錯誤時退出迴圈。

我們以斐波那契數列為例,寫一個Fib類,可以作用於for迴圈:

class Fib(object):
    def __init__(self):
        self.a, self.b = 0, 1 # 初始化兩個計數器a,b

    def __iter__(self):
        return self # 例項本身就是迭代物件,故返回自己

    def next(self):
        self.a, self.b = self.b, self.a + self.b # 計算下一個值
        if self.a > 100000: # 退出迴圈的條件
            raise StopIteration();
        return self.a # 返回下一個值

現在,試試把Fib例項作用於for迴圈:

>>> for n in Fib():
...     print n
...
1
1
2
3
5
...
46368
75025

更多定製類翻看部落格

  • 使用元類

type()和metaclass(元類)

先定義metaclass,就可以建立類,最後建立例項。metaclass允許你建立類或者修改類。換句話說,你可以把類看成是metaclass創建出來的“例項”。