1. 程式人生 > >python 面向對象九 定制類

python 面向對象九 定制類

此外 mys 解決 rep 索引 沒有 註意 instance dict

一、定制類,實質就是我們自己重寫特殊函數

看到類似__slots__這種形如__xxx__的變量或者函數名就要註意,這些在Python中是有特殊用途的。

__slots__我們已經知道怎麽用了,__len__()方法我們也知道是為了能讓class作用於len()函數。

除此之外,Python的class中還有許多這樣有特殊用途的函數,可以幫助我們定制類。

二、__len__()方法

>>> class MyStr(str):
      def __init__(self, s):
          self.__s = s
      def __len__(self):
          
return len(self.__s) - 1 >>> s = MyStr(abc) >>> len(s) 2

三、__str__()方法

>>> class Student(object):
...     def __init__(self, name):
...         self.name = name
...     def __str__(self):
...         return Student object (name: %s) % self.name
...
>>> print(Student(
Michael)) Student object (name: Michael)

四、__repr__()方法

>>> s = Student(Michael)
>>> s
<__main__.Student object at 0x109afb310>

這是因為直接顯示變量調用的不是__str__(),而是__repr__(),兩者的區別是__str__()返回用戶看到的字符串,而__repr__()返回程序開發者看到的字符串,也就是說,__repr__()是為調試服務的。

解決辦法是再定義一個__repr__()。但是通常__str__()

__repr__()代碼都是一樣的,所以,有個偷懶的寫法:

class Student(object):
    def __init__(self, name):
        self.name = name
    def __str__(self):
        return Student object (name=%s) % self.name
    __repr__ = __str__

五、__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 # 返回下一個值
>>> for n in Fib():
...     print(n)
...
1
1
2
3
5
...
46368
75025

六、__getitem__()方法

class Fib(object):
    def __getitem__(self, n):
        if isinstance(n, int): # n是索引
            a, b = 1, 1
            for x in range(n):
                a, b = b, a + b
            return a
        if isinstance(n, slice): # n是切片
            start = n.start
            stop = n.stop
            if start is None:
                start = 0
            a, b = 1, 1
            L = []
            for x in range(stop):
                if x >= start:
                    L.append(a)
                a, b = b, a + b
            return L

但是沒有對step參數作處理,

也沒有對負數作處理,所以,要正確實現一個__getitem__()還是有很多工作要做的。

此外,如果把對象看成dict__getitem__()的參數也可能是一個可以作key的object,例如str

與之對應的是__setitem__()方法,把對象視作list或dict來對集合賦值。最後,還有一個__delitem__()方法,用於刪除某個元素。

總之,通過上面的方法,我們自己定義的類表現得和Python自帶的list、tuple、dict沒什麽區別,這完全歸功於動態語言的“鴨子類型”,不需要強制繼承某個接口。

python 面向對象九 定制類