Python學習(7)——面向物件高階編輯
1、使用__slots__
(1)可以嘗試給例項繫結一個方法:
def set_age(self, age):
self.age = age
from types import MethodType
s.set_age = MethodType(set_age, s) # 給例項繫結一個方法
(2)但是,給一個例項繫結的方法,對另一個例項是不起作用的
(3)為了給所有例項都繫結方法,可以給class繫結方法:
def set_score(self, score): self.score = score Student.set_score = set_score
(4)Python允許在定義class的時候,定義一個特殊的__slots__
變數,來限制該class例項能新增的屬性
(5)__slots__
定義的屬性僅對當前類例項起作用,對繼承的子類不起作用
(6)子類例項允許定義的屬性就是自身的__slots__
加上父類的__slots__
2、
使用@property
(1)對於類的方法,裝飾器一樣起作用。Python內建的@property
裝飾器就是負責把一個方法變成屬性呼叫的
(2)還可以定義只讀屬性,只定義getter方法,不定義setter方法就是一個只讀屬性
3、多重繼承
(1)MixIn有點類似於Object-C的protocol,但MixIn是類,有可呼叫的方法和屬性
(2)Python允許使用多重繼承
4、定製類
(1)__len__()
方法是為了能讓class作用於len()
函式
(2)定義__str__()
方法,返回一個好看的字串,print(s)可以呼叫到例項s的__str__方法
(3)__str__()
返回使用者看到的字串,而__repr__()
返回程式開發者看到的字串
(4)通常__str__()
和__repr__()
程式碼都是一樣的,所以,有個偷懶的寫法:__repr__ = __str__
(5)一個類想被用於for ... in
迴圈,就必須實現一個__iter__()
方法,該方法返回一個迭代物件,Python的for迴圈就會不斷呼叫該迭代物件的__next__()
StopIteration
錯誤時退出迴圈:raise StopIteration()
(6)要表現得像list那樣按照下標取出元素,需要實現__getitem__()
方法
(7)__getitem__()
傳入的引數可能是一個int,也可能是一個切片物件slice
(8)
如果把物件看成dict
,__getitem__()
的引數也可能是一個可以作key的object;與之對應的是__setitem__()
方法,把物件視作list或dict來對集合賦值
(9)還有一個__delitem__()
方法,用於刪除某個元素
(10)呼叫不存在的屬性時,Python直譯器會試圖呼叫__getattr__(self, 'xxx')
來嘗試獲得屬性(REST API,鏈式呼叫)
(11)任何類,只需要定義一個__call__()
方法,就可以直接對例項進行呼叫
(12)能被呼叫的物件就是一個Callable
物件,比如函式和帶有__call__()
的類例項,通過callable()
函式,我們就可以判斷一個物件是否是“可呼叫”物件:callable([1, 2, 3])
還有很多可定製的方法,請參考Python的官方文件
5、使用列舉類
(1)為列舉型別定義一個class型別,每個常量都是class的一個唯一例項。Python提供了Enum
類來實現這個功能:
from enum import Enum
Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))
可以直接使用Month.Jan
來引用一個常量,或者列舉它的所有成員:
for name, member in Month.__members__.items():
print(name, '=>', member, ',', member.value)
value
屬性則是自動賦給成員的int
常量,預設從1
開始計數。
(2)如果需要更精確地控制列舉型別,可以從Enum
派生出自定義類:
from enum import Enum, unique
@unique
class Weekday(Enum):
Sun = 0 # Sun的value被設定為0
Mon = 1
Tue = 2
Wed = 3
Thu = 4
Fri = 5
Sat = 6
@unique
裝飾器可以幫助我們檢查保證沒有重複值
6、使用元類
(1)type()
函式可以檢視一個型別或變數的型別,class的型別是type
(2)
可以通過type()
函式創建出Hello
類,而無需通過class Hello(object)...
的定義
(3)要建立一個class物件,type()
函式依次傳入3個引數:
- class的名稱;
- 繼承的父類集合,注意Python支援多重繼承,如果只有一個父類,別忘了tuple的單元素寫法;
- class的方法名稱與函式繫結,這裡我們把函式
fn
繫結到方法名hello
上。
(4)metaclass,直譯為元類
先定義metaclass,就可以建立類,最後建立例項(ORM)