《Dive into Python》讀書筆記之對象和麪向對象

Chapter 5:對象和麪向對象

兩種import方法

import random   # 使用時需要加上random前綴
random.randint  # <bound method Random.randint of <random.Random object at 0x10101f620>>
randint         # name 'randint' is not defined
from random import randint  # 可以直接使用
randint         # <bound method Random.randint of <random.Random object at 0x10101f620>>
from random import *    # 導入所有方法

類的定義

from UserDict import UserDict
class FileInfo(UserDict):   # 創建FileInfo類並繼承UserDict類
    "store file metadata"   # 類的docstring
    def __init__(self, filename=None):  #【1】
        UserDict.__init__(self)         #【2】
        self["name"] = filename         #【3】

【1】:__init__類似構造函數,self爲每一個類方法都需要指定的參數,調用時不需指定,會自動加上。
【2】:Python不會自動調用父類的構造函數,必須顯式調用父類合適的方法,包括__init__函數。
【3】:一般只能用self.name方式來指定成員變量,但此處因爲繼承了UserDict類,所以可以使用self["name"]方法來賦值。參考stackoverflow上的一篇文章:http://stackoverflow.com/questions/4117060/confused-by-selfname-filename

垃圾回收

當指派給實例的變量超出作用域時,python會自動釋放其空間。在下面的代碼中,每一次執行leakmem函數時,之前的f已經超出了作用域被銷燬,故執行過程中始終只有一個實例,不會發生內存泄漏。

def leakmem(): 
    f = fileinfo.FileInfo('/music/_singles/kairo.mp3') 

for i in range(100):
    leakmem()

探索UserDict:一個封裝類

  • 可以在ipython中from UserDict import UserDict,再用UserDict?查看其內容和相關屬性。
  • 在 Python 2.2 之前的版本中,你不可以直接子類化字符串、列表以及字典之類的內建數據類型。作爲補償,Python 提供封裝類來模擬內建數據類型的行 爲,比如:UserStringUserList 和 UserDict。通過混合使用普通和特殊方法, UserDict 類能十分出色地模仿字典。在 Python 2.2 和其後的版本中,你可以直 接從 dict 內建數據類型繼承。這樣之前的代碼可以改寫成如下代碼。且無需導入UserDict模塊和初始化子類。
  • 考慮兩個類,base 和 child,base 中的 方法 a 需要調用 self.b;而我們又在 child 中覆蓋了方法 b。然後我們創建一個 child 的實例,ch。調用 ch.a,那麼此時的方法 a 調用的 b 函數將不是 base.b, 而是 child.b。
class FileInfo(dict): 
    "store file metadata"
    def __init__(self, filename=None):
        self["name"] = filename

專用類方法

  • __getitem__:使類可以模擬使用instance["key"]語句,即使用該語句時,python自動調用instace.__getitem__("key")方法,下同
  • __setitem__:模擬instance["key"] = value
  • __repr__: 返回對象的機器友好的字符串表示
  • __str__: 返回對象的人類友好的字符串表示,兩者的區別詳見此處
  • __cmp__: 模擬cmp(instance1, instance2)
  • __len__: 模擬len(instance)
  • __delitem__ 模擬del instance[key]
  • 更多專用類方法詳見官方文檔

類屬性

在 Java 中,靜態變量 (在 Python 中叫類屬性) 和實例變量 (在 Python 中叫數 據屬性) 兩者都是緊跟在類定義之後定義的 (一個有 static 關鍵字,一個沒有)。 在 Python 中,只有類屬性可以定義在這裏,數據屬性定義在 __init__ 方法中

class counter:
    count = 0   # 緊跟類名定義類屬性
    def __init__(self):
    self.__class__.count += 1   # 通過該方法修改類屬性 【1】

counter.count   # 0
c = counter()   
c.count         # 1
counter.count   # 1
d = counter()
d.count         # 2
c.count         # 2
counter.count   # 2

【1】:__class__ 是每個類實例的一個內置屬性 (也是每個類的)。它是一個類的引 用,而 self 是一個類 (在本例中,是 counter 類) 的實例。

私有函數

  • 如果一個 Python 函數,類方法,或屬性的名字以兩個下劃線開始 (但不是結束),它是私有的;其它所有的都是公有的。
  • 在 Python 中,所有的專用方法 (像 __setitem__) 和內置屬性 (像 __doc__) 遵守一 個標準的命名習慣:開始和結束都有兩個下劃線。命名自己的私有函數時要避免這種做法。
class Test:
    def _print(self):
        print "hello, world!"
    def __print(self):
        print "can you see me?"

t = Test()  
t._print()   # "hello, world!"
t.__print()  # AttributeError: Test instance has no attribute '__print'
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章