python基礎語法總結(六)-- python類與OOP面向物件特性
阿新 • • 發佈:2018-12-22
python基礎語法總結(一)-- python型別轉換函式+檔案讀寫
目錄
一. 類
1. 定義
### 定義類 class Animal: # 定義一個類animal """測試類Animal""" color = "black" # 定義屬性:顏色 age = 0 # 定義屬性:年齡 name = "" # 定義姓名:name def jump(self): # 定義類的方法,方法第一個入參必須是例項本身,可以不用字面量'self'表示,但本質仍然是例項本身為入參 print("can't jump") def eat(self, food): # 有引數的方法 print("eat " + food) def __healthy(self): # 私有方法 print("easy") __habit = "think" # 定義私有變數, 以__雙下劃線開頭的屬性,為私有屬性 def get_habit(self): # 讀取私有屬性 """得到私有屬性__habit的值""" return self.__habit def set_habit(self, habit): # 修改私有屬性 """設定私有屬性__habit的值""" self.__habit = habit # 專有方法,以__開始,並且以__結束,有特殊的用途 def __init__(self, **args): #_init__()方法,在構造例項時,預設呼叫此方法創建出例項 """專有方法__init__()""" if args: if 'name' in args.keys(): self.name = args['name'] if 'age' in args.keys(): self.age = args['age'] if 'color' in args.keys(): self.color = args['color']
2. 建立例項物件
### 建立類的例項
xh = Animal()
mm = Animal(color="Red", age=3) # 呼叫的時 __init__方法
3. 讀寫屬性和呼叫方法
# 讀取例項的公有屬性 print(xh.color) # 訪問color屬性,得到預設值:black print(mm.color) # 訪問color屬性,得到初始化的值Red # 修改例項的公有屬性 xh.name = '小黃' # 設定name屬性為:小黃 print(xh.name) # 可以看到name屬性確實改為:小黃 mm.age = 5 print(mm.age) # age改為5 # 私有屬性在類的外部無法讀取和修改,可以通過公有方法來讀寫 print(xh.__habit) # 報錯:'Animal' object has no attribute '__habit' print(xh.get_habit()) # 正確,得到私有屬性的值:think # 呼叫類的公有方法 xh.jump() # 第一個預設入參self不用寫, 列印: can't jump xh.eat("meat") # 呼叫有引數的方法,self同樣不用寫
二. 繼承
1. 繼承語法
### 繼承
class Cat(Animal): # 繼承父類animal,得到父類所有公有屬性和公有方法
"""新建類Cat,繼承自父類 Animal"""
def __init__(self):
super().__init__(color='white') # 呼叫父類的init方法,設定初始值color顏色為white
# print(__habit) 私有屬性不能繼承,這裡會報錯
mimi = Cat() # 新建物件mimi
print(mimi.color) # 顏色為white,預設值
2. 多繼承
## python支援多繼承
class A:
"""定義A父類"""
__a = 'A'
def show(self):
print(self.__a)
class B:
"""定義B父類"""
__b = "B"
def show(self):
print(self.__b)
class SubClass(A, B): # 多繼承在括號內寫入所有要繼承的類,順序--從左到右
"""定義SubClass類,繼承A、B類"""
pass # 佔位
sub = SubClass()
sub.show() # 因為順序從左到右,所以show()方法繼承自第一個有show()的父類:A
3. 指定多繼承下的繼承源
# 指定屬性或方法的繼承源
class SubClass(A,B): # 多繼承在括號內寫入所有要繼承的類,順序--從左到右
"""定義SubClass類,繼承A、B類"""
show = B.show # 指定子類的show為父類B的show
sub = SubClass()
sub.show() # 因為指定B.show,所以子類的show()方法執行結果為:B
三. 操作符過載
### 操作符過載
class SpecalList:
"""操作符過載測試類"""
__list = []
def __init__(self, l):
self.__list = l
def __add__(self, other): # 過載__add__()操作符,使得SpecalList有特殊的 + 運算子實現
"""建立合併兩個list的 + 操作符實現"""
result = self.__list
for item in other.getList():
result.append(item)
return SpecalList(result)
def getList(self):
return self.__list
# 呼叫實現
list1 = SpecalList([1,2,3])
list2 = SpecalList([8,7,6])
list3 = list1 + list2 # 通過操作符+, 實現呼叫__add__()方法
print(list3.getList()) # 可以看到結果為:[1, 2, 3, 8, 7, 6]
運算子與專有方法的對應關係 + __add__() - __sub__() * __mul__() / __div__() % __mod__() ** __pow__() len() __len__()
四. 靜態方法、類方法、抽象方法
可以參考文章:《Python 中的 classmethod 和 staticmethod 有什麼具體用途?》
1. 靜態方法
@staticmethod註解
class StaticClass:
"""靜態方法"""
@staticmethod # 關鍵字
def treble_string(string): # 靜態方法,不需要有self入參
return string * 3
StaticClass.treble_string("abc") # 直接呼叫,不用建立例項,本例:'abcabcabc'
2. 類方法
import math
class Pizza:
"""類方法"""
def __init__(self, radius, height):
self.radius = radius
self.height = height
@staticmethod
def compute_area(radius):
return math.pi * (radius ** 2)
@classmethod # 類方法的關鍵字
def compute_volume(cls, height, radius): # 類方法第一個引數是類本身
'''類方法與靜態方法畢肖像,使用類方法主要是為了避免硬編碼類名本身.
如果不使用類方法而改用靜態方法@staticmethod,那麼在呼叫本類其他方法和屬性時,將不得不硬編碼(本例需要寫:Pizza.compute_area(),硬編碼寫了Pizza)
這樣在Pizza類被繼承後,compute_volume()這個方法可能會有問題,重寫的方法和屬性無效 '''
return height * cls.compute_area(radius)
def get_volume(self):
return self.compute_volume(self.height, self.radius)
# 呼叫類方法
Pizza.compute_volume(3,1) # 返回計算的體積9.42477796076938
3. 抽象方法
import abc
from abc import ABCMeta
class AbstractClass(metaclass=ABCMeta): # 引入抽象基礎類
"""抽象類測試"""
def method1(self): # 設定method1()為抽象方法
""" python本身的語法沒有抽象方法,子類可以直接重寫此方法,來達到抽象方法的效果,這裡定義一個空方法就可以
但是method1()這種方式有很大問題,如果程式設計師忘記重寫,程式本身不會提示,這樣不利於開發和除錯"""
def method2(self):
""" 在要設定的抽象方法method2()中,方法體主動丟擲異常
但這樣也有小問題,只有在呼叫method2()時,才會報錯,在編譯階段沒有提醒"""
raise NotImplementedError
@abc.abstractmethod
def method3(self):
""" 引入@abc.abstractmethod,在開發(依賴IDE工具自身的檢測)和編譯階段如果檢查出子類沒有重寫此方法,則會報錯"""
class SubClass(AbstractClass):
"""抽象類的子類,要重寫父類抽象方法"""
def method1(self):
print("method1")
def method2(self):
print("method2")
def method3(self):
print("method3")
sc = SubClass() # 如果沒有重寫抽象類method3(),這裡會報錯
sc.method2()
sc.method3()