類和對象
類的構造方法 def __init__():
1 class People:
2 def __init__(self,name): 3 self.name = name
注意:在構造方法中的變量不用再次聲明,必須有self,創建類的對象是用=
類的私有成員
讓方法或者類變為私有,只要在它的名字前加上雙下划線
1 class People:
2 __name = 'laowang'
3 def getname(self): 4 return self.__name
注意:類的私有成員可以通過方法訪問,也可以通過 _類名__私有成員這種格式來訪問
類的繼承
class 子類(父類、基類、超類)
在繼承構造函數的過程中,可以用以下兩個方法,推薦方法2:
(1)調用未綁定的父類構造方法
1 class People:
2 def __init__(self): 3 self.name = 'aa' 4 class Student(People): 5 def __init__(self): 6 People.__init__(self) 7 self.son = 20
(2)使用super
class People:
def __init__(self): self.name = 'aa' class Student(People): def __init__(self): super().__init__() self.son = 20
super可以不帶任何參數,但是當父類中有參數傳入,super后的__init__要加上參數而且不能加上self
1 class People:
2 def __init__(self,name): 3 self.name = name 4 class Student(People): 5 def __init__(self,name,sno): 6 super().__init__(name) 7 self.name = name 8 self.sno = sno
類的組合
類之間沒用明顯繼承關系可以用組合,比如一個電話簿的類由電話和地址類組合起來:
1 class Tel:
2 def __init__(self,x): 3 self.info = x 4 5 class Add: 6 def __init__(self,y): 7 self.info = y 8 9 class Notebook: 10 def __init__(self,x,y): 11 self.tel = Tel(x) 12 self.add = Add(y) 13 def print_info(self): 14 print("Tel:%s\nAdd:%s" %(self.tel.info,self.add.info))
類 類對象 實例對象
類對象就像C++中的static變量,一個對象有了實例對象后就將類對象的值覆蓋了
屬性名如果和方法名相同,屬性會覆蓋方法
綁定
對象.__dict__返回對象擁有的屬性
對象調用后方法綁定到實例對象上del類后,a的方法還是存在的,因為A的方法和屬性都是static,程序退出前不會消失
一些和類相關的BIF
issubclass(class, classinfo)
isinstance(object, classinfo)
hasattr(object, name) 注意第二個參數要用字符串格式
getattr(object, name[, default])
setattr(object, name, value) 設置屬性
delattr(object, name) 刪除屬性,屬性不存在拋出異常
property()
為什么用property
首先一個實例化的對象可以進行直接的賦值和修改,如c.age = 10,但是這樣沒法做參數檢查,我就可以讓c.age = 1000,這顯然是不合理的
於是,用方法可以對參數進行檢查,可以用c.setage(66)來設置年齡,但是這樣就不方便了
函數property的基本功能就是把類中的方法當作屬性來訪問,為什么用方法來操作
1 class C: 2 def __init__(self,age = 10): 3 self.age = age 4 def getage(self): 5 return self.age 6 def setage(self,value): 7 if 0 <= value <= 120: 8 self.age = value 9 else: 10 print("年齡非法") 11 def delage(self): 12 del self.age 13 x = property(getage,setage,delage)
魔法方法
(1)構造和析構
魔法方法總是被雙下划線包圍,它們總能在適當的時候自動被調用
__init__(self) 不能有返回值
__new__(cls[,]) 返回一個類對象,python自動調用,一般不需要重寫,依照Python官方文檔的說法,__new__方法主要是當你繼承一些不可變的class時(比如int, str, tuple), 提供給你一個自定義這些類的實例化過程的途徑。
__del__(self) del一個對象的時候被調用
(2)屬性和訪問
__getattr__(self,name) 定義當用戶試圖獲取一個不存在的屬性時的行為
__getattribute__(self,name) 定義當該類屬性被訪問時的行為
__setattr__(self,name,value) 定義當一個屬性被設置的行為
__delattr__(self,name) 定義當一個屬性被刪除的行為
程序1:查看屬性方法何時被調用
1 class C: 2 def __getattribute__(self,name): 3 print("getattribute") 4 return super().__getattribute__(name) 5 def __getattr__(self,name): 6 print("getattr") 7 def __setattr__(self,name,value): 8 print("setattr") 9 super().__setattr__(name,value) 10 def __delattr__(self,name): 11 print("delattr") 12 super().__delattr__(name)
當訪問一個不存在的屬性,就調用先調用getattribute,在調用getattr,訪問存在的屬性調用getattribut后顯示其值
程序2:寫一個矩形類,默認有寬高兩個屬性,如果給一個叫square的屬性復制,那么說明這是一個正方形(Python基礎教程151,小甲魚45)
1 class Rectangle: 2 def __init__(self,width = 0,height = 0): 3 self.width = width 4 self.height = height 5 def __setattr__(self,name,value): 6 if name == "square": 7 self.width = value 8 self.height = value 9 else: 10 self.__dict__[name] = value 11 def getarea(self): 12 return self.width * self.height
(3)描述符(property的原理)
描述符就是將某種特殊類型的類的實例指派給另一個類的屬性
__get__(self,instance,owner) 用於訪問屬性,它返回屬性的值
__set__(self,instance,value) 將在屬性分配操作中調用,不返回任何內容
__delete__(self,instance) 控制刪除操作,不返回任何內容
(4)定制容器(Python基礎教程144,小甲魚47)
定制的容器對象是不可變的,需要前兩個魔法方法;可變的需要4個魔法方法
1. 如果說你希望定制的容器是不可變的話,你只需要定義 __len__() 和 __getitem__() 方法。
2. 如果你希望定制的容器是可變的話,除了 __len__() 和 __getitem__() 方法,你還需要定義 __setitem__() 和__delitem__() 兩個方法。
迭代器
BIF:iter()返回一個迭代器,next()返回下一個元素
對應的魔法方法__iter__() __next__()
用迭代器寫的裴波那切數列:
1 class Fibs: 2 def __init__(self,n = 10): 3 self.a = 0 4 self.b = 1 5 self.n = n 6 def __iter__(self): 7 return self 8 def __next__(self): 9 self.a,self.b = self.b,self.a+self.b 10 if self.a > self.n: 11 raise StopIteration 12 return self.a
生成器
生成器是迭代器的一種實現
用yield或者圓括號
yield
圓括號