Python面向对象-特殊成员
我們知道類中有字段、方法和屬性三大類成員,并且成員名前如果有兩個下劃線,則表示該成員是私有成員,私有成員只能由類內部調用。
Python的類成員還存在著一些具有特殊含義的成員,其中有一些比較重要的,我們一一來看:
(1) __init__
構造方法,通過類創建對象時,自動觸發執行。
1 class Student(object): 2 def __init__(self, name): 3 self.name = name 4 5 ...(2) __del__
析構方法,當對象在內存中被釋放時,自動觸發執行。
注:此方法一般無須定義,因為Python是一門高級語言,程序員在使用時無需關心內存的分配和釋放,因為此工作都是交給Python解釋器來執行,所以,析構函數的調用是由解釋器在進行垃圾回收時自動觸發執行的
1 class Student(object): 2 ... 3 4 def __del__(self): 5 pass(3)?__call__
我們已經知道了類名后面加()是調用__init__方法,那對象后面加()呢?請看下面的代碼:
1 class Student(object): 2 def __init__(self, name): 3 self.name = name 4 5 def __call__(self): 6 print(self.name) 7 8 ... 9 10 mike = Student("Mike") 11 mike()程序輸出是:?Mike?,我們可以看到對象()會調用__call__方法,我們可以通過callable()函數判斷對象是否可以調用
(4)?__dict__
有沒有辦法獲取對象里所有普通字段及其值呢?Python為我們提供了__dict__:
1 class Student(object): 2 Nation = "China" 3 4 def __init__(self, name): 5 self.name = name 6 self.score = 0 7 8 ... 9 10 mike = Student("Mike") 11 print(mike.__dict__)程序輸出:?{'score': 0, 'name': 'Mike'}?,對于靜態字段Nation = "China",__dict__內并不包含
(5) __str__ , __repr__?
對于一個對象,我們對其使用print時,默認程序輸出的是對象的內存地址:
1 class Student(object): 2 def __init__(self, name): 3 self.name = name 4 self.score = 0 5 6 ... 7 8 mike = Student("Mike") 9 print(mike)程序輸出:?<__main__.Student object at 0x0050F7B0>?
怎么才能打印得好看呢?只需要定義好__str__()方法,返回一個好看的字符串就可以了:
1 class Student(object): 2 def __init__(self, name): 3 self.name = name 4 self.score = 0 5 6 def __str__(self): 7 return self.name 8 ... 9 10 mike = Student("Mike") 11 print(mike)程序輸出就是__str__方法的返回值:?Mike?
如果我們把上面的代碼在idle里運行,并敲下mike時(>>>mike),打印出來的還是對象的地址,
這是因為直接顯示變量調用的不是__str__(),而是__repr__(),兩者的區別是__str__()返回用戶看到的字符串,而__repr__()返回程序開發者看到的字符串,也就是說,__repr__()是為調試服務的。
解決辦法是再定義一個__repr__()。但是通常__str__()和__repr__()代碼都是一樣的,所以,有個偷懶的寫法:
1 class Student(object): 2 def __init__(self, name): 3 self.name = name 4 self.score = 0 5 6 def __str__(self): 7 return self.name 8 __repr__ = __str__(6)?__iter__
如果一個類想被用于for ... in循環,類似list或tuple那樣,就必須實現一個__iter__()方法,該方法返回一個迭代對象,然后,Python的for循環就會不斷調用該迭代對象的__next__()方法拿到循環的下一個值,直到遇到StopIteration錯誤時退出循環。
我們以斐波那契數列為例,寫一個Fib類,可以作用于for循環:
1 class Fib(object): 2 def __init__(self, maximum): 3 self.a = 0 4 self.b = 1 # 初始化兩個計數器a,b 5 self.maximum = maximum # 定義停止循環的條件 6 7 def __iter__(self): 8 return self # 實例本身就是迭代對象,故返回自己 9 10 # Python的for循環就會不斷調用該迭代對象的__next__()方法拿到循環的下一個值,直到遇到 11 # StopIteration錯誤時退出循環 12 def __next__(self): 13 self.a, self.b = self.b, self.a + self.b 14 if self.a > self.maximum: 15 raise StopIteration() 16 return self.a 17 18 for item in Fab(100): 19 print(item)(7)?__getitem__、__setitem__、__delitem__
上面的Fib類的對象雖然能作用于for循環,看起來和list有點像,但是,把它當成list來使用還是不行,比如,取第4個元素:
1 Fib(100)[4] 2 TypeError: 'Fib' object does not support indexing要表現得像list那樣按照下標取出元素,需要實現__getitem__()方法
1 def __getitem__(self, i): 2 a, b = 0, 1 3 for x in range(i): 4 a, b = b, a + b 5 if a <= self.maximum: 6 return a 7 else: 8 raise ValueError("Out of range")現在,就可以按下標訪問數列的任意一項了:?print("Fib(100)[4]:", Fib(100)[4])?,輸出是:?Fib(100)[4]: 3?
list還有個神奇的切片方法,Fib該如何實現呢?__getitem__()傳入的參數可能是一個int,也可能是一個切片對象slice,所以要做判斷:
1 def __getitem__(self, i): 2 if isinstance(i, int): 3 a, b = 0, 1 4 for x in range(i): 5 a, b = b, a + b 6 if a <= self.maximum: 7 return a 8 else: 9 raise ValueError("Out of range") 10 elif isinstance(i, slice): 11 if isinstance(i, slice): # i是切片 12 start = i.start 13 stop = i.stop 14 if start is None: 15 start = 0 16 a, b = 1, 1 17 L = [] 18 for x in range(stop): 19 if x >= start: 20 L.append(a) 21 a, b = b, a + b 22 return L但是沒有對step參數作處理,也沒有對負數作處理,所以,要正確實現一個__getitem__()還是有很多工作要做的。
此外,如果把對象看成dict,__getitem__()的參數也可能是一個可以作key的object,例如str。
與之對應的是__setitem__()方法,把對象視作list或dict來對集合賦值。最后,還有一個__delitem__()方法,用于刪除某個元素:
1 def __getitem__(self, i): 2 if isinstance(i, int): # 對應于list, tuple的索引 3 a, b = 0, 1 4 for x in range(i): 5 a, b = b, a + b 6 if a <= self.maximum: 7 return a 8 else: 9 raise ValueError("Out of range") 10 elif isinstance(i, slice): # 對應于list,tuple的切片 11 if isinstance(i, slice): # i是切片 12 start = i.start 13 stop = i.stop 14 if start is None: 15 start = 0 16 a, b = 1, 1 17 L = [] 18 for x in range(stop): 19 if x >= start: 20 L.append(a) 21 a, b = b, a + b 22 return L 23 elif isinstance(i, str): # 對應于字典的dic[key]或dic.get[key] 24 print(type(i)) 25 else: 26 print("wrong type") 27 28 def __setitem__(self, key, value): # 對應于字典的dic[key] = value 29 print("key:value", key, value) 30 31 def __delitem__(self, key): # 對應于del dic[key] 32 print("del", key)?
轉載于:https://www.cnblogs.com/z-joshua/p/6398231.html
總結
以上是生活随笔為你收集整理的Python面向对象-特殊成员的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 亚瑟王(bzoj 4008)
- 下一篇: ---Mybatis3学习笔记(2)