面向對象
- 用面向對象的思維去解決問題。
- 將某一類事物相關的屬性和方法封裝在一起,用來表示這類事物
- 面向對象,借鑑函數的封裝思維,再次對函數和變量進行封裝,來提高代碼的複用性
class 使用class關鍵字定義類
- 為了便於區分,把用關鍵字 class 定義的代碼塊稱為 類
- 命名時使用峰駝命名法,即首字母大寫
- 在類裡面的變量稱為 類的屬性
- 在類裡面的函數稱為 類的方法
- self 是實例自己
- __init__ 是初始化函數,在實例化時會自動調用
- 實例通過點(.)操作來調用屬性或者方法
類的析構函數
- 在類中增加__del__函數,當刪除實例的時候,就會調用此方法
- del關鍵字用來刪除對象
- 案例:
<code>class Person: #定義一個類
\tdef __init__(self,name,age,sex='男'):#初始化實例函數
\t\tself.name = name
\t\tself.age = age
\t\tself.sex = sex
\tdef paly(self):
\t\tprint(f'{self.name}正在玩遊戲!')
\tdef search(self):
\t\tprint(f'{self.name}正在查找資料')
\tdef __del__(self):
\t\tprint(f'{self.name}事情做完了')
morang = Person('莫讓龍',18) #實例化對象
morang.name #調用實例化對象的屬性
morang.play() #調用實例化對象的方法
del morang #刪除實例化對象/<code>
繼承和重用
- 繼承:
- 所有的類都繼承與object
- 通過繼承可以很好的提高代碼的複用性
- 通過在類後面的跟上要繼承的類來確定父類
- 多繼承時,只需要在繼承時增加需要繼承的類即可
- __base__ 調用時,可以看到繼承的第一個類
- __bases__ 調用時,可以查看繼承的所有類
- mro 方法查看繼承順序
- 重用:
- 子類重新定義父類方法,讓同一方法有不同的行為
- 如果子類想繼續使用父類的行為,推薦使用super函數方法來實現
mix-in 設計模式 基於多繼承的方式的
常用內置函數
- 1、屬性訪問函數
- hasattr(a,'b') 判斷a裡有沒有b屬性
- getattr(a,'b') 獲取a裡面b屬性的值
- setattr(a,'b','c') 設置 a裡面b屬性的值為 c (有則改,無則增加)
- delattr(a,'b') 刪除a裡的b屬性
- 注意:屬性名需要加上引號attr即attribute的縮寫
- 三目運算確保f得到屬性值:
<code>f = getattr(a,'b') if hasattr(a,'b') else setattr(a,'b','c')/<code>
- 2、對象關係方法
- issupclass(a,b) 判斷a是不是b的子類
- isinstance(a,b) 判斷實例a是不是b的實例
- isinstance 多用於判斷類型 :
- isinstance(a,int) 判斷a是不是int類型
- isinstance(a,(int,float)) 判斷a是不是int或者float類型
- type 也可以判斷,但是隻能判斷單個類,一般很少使用
- 3、魔法方法
- Python中很多內置方法都是兩個下劃線在兩邊,中間是單詞名字,並且這樣的方法名字有一定的特殊的含義,把這種方法都稱之為魔法方法
- __new__方法,就是最開始調用的一個方法,會在初始化之前自動調用
- 例如:def __new__(cls,*args,**kwargs): #cls 類本身
- 單例模式:類始終只有一個實例存在,不會同時出現多個實例
<code>def __new__(cls,*args,**kwargs):
\tif not hasattr(cls,'_instance'):
\t\tcls._instance = super().__new__(cls)
\t\treturn cls._instance/<code>
利用__new__方法,可以很方便的去實現一個類的單例模式
- 4、輸出魔法方法
- __str__ 修改print打印時的樣子
- __repr__ 修改直接打印時的樣子
- __call__ 讓實例化對象向函數一樣去使用
- 例如:
<code>def __str__(self):
\treturn 'this is str %s' %self.name
def __repr__(self):
\treturn 'this is repr %r' %self.name
def __call__(self,num):
\tnum = num*10
\tprint(num)/<code>
- 5、協議
- Python中有很多的協議,比如序列協議等很多協議,只要遵守這些協議,既可以說是對應的類型,比如定義了序列類型協議,則定義的類就是序列類型
- (1)序列協議
- __len__, __getitem__,__setitem__,__delitem__等協議,如果不需要改變,那後兩個就不要定義。
<code>class IndexTuple:
\tdef __init__(self,*args):
\t\tself.values = tuple(i for i in *args)
\t\tself.index = tuple(enumerate(self.values))#enumerate 枚舉方法
\tdef __len__(self):
\t\treturn len(self.values)
\tdef __getitem__(self,key):
\t\treturn self.index[key][1]
\tdef __repr__(self):
\t\treturn str(self.values) #repr 需要返回字符串模式/<code>
- (2)迭代器協議
- 只要類實現了__iter__ 和 __next__ 方法,則這個類就是迭代器,因此只要實現這兩個方法,則是可以迭代對象
<code>class Number:
\tdef _init__(self,end=10):
\t\tself.start = 0
\t\tself.end = end
\tdef __iter__(self):
\t\treturn self
\tdef __next__(self):
\t\tself.start += 1
\t\tif self.start >= self.end:
\t\t\traise StopIteration
\t\treturn self.start/<code>
- (3)上下文協議
- 只要類裡面定義__enter__和__exit__這兩個方法,則可以使用with去使用此對象
- 案例:計算函數運行的時間
<code>import time
class RunTime:
\tdef __enter__(self):
\t\tself.start_time = time.time()
\t\treturn self.start_time
\tdef __exit__(self,exc_type,exc_val,exc_tb):
#exc_type、exc_val、exc_tb 固定三個參數必須寫,應用時可以不傳值
\t\tself.end_time = time.time()
\t\tself.run_time = self.end_time -self.start_time
\t\tprint('運行時間為%s' %self.run_time)/<code>
閱讀更多 槑孨 的文章