多型、多型性
多型
多型通俗理解起來,就像迪迦奧特曼有三種形態一樣,怎麼變還是迪迦奧特曼
- 定義:多型指的是一類事物有多種形態
示例如下:
'''動物有多種表現形態,人也是動物之一,在這裡會說話就是動物'''
class Animal():
def speak(self):
print('動物發出的叫聲--->', end='')
class Cat(Animal):
def speak(self):
print('喵喵喵')
class Dog(Animal):
def speak(self):
print('汪汪汪')
class People(Animal):
def speak(self):
print('啊啊啊')
ani = Animal()
ani.speak()
cat = Cat()
cat.speak()
ani.speak()
dog = Dog()
dog.speak()
ani.speak()
peo = People()
peo.speak()
# 結果
動物發出的叫聲--->喵喵喵
動物發出的叫聲--->汪汪汪
動物發出的叫聲--->啊啊啊
多型性
- 多型性是指可以不用考慮物件具體型別的情況下直接使用物件,多型性是同一個操作,作用到不同例項而表現出不同實現方式的特性
拿上例來說:
# 多型性
# 統一介面,歸一化操作
def Speack(animal):
animal.speak()
'''
因為所有的動物都會“說”,是同一操作,但是呼叫的引數不同,輸出的結果不同,這就是多型性的體現
'''
Speack(cat)
Speack(dog)
Speack(peo)
# 結果
喵喵喵
汪汪汪
啊啊啊
多型性的優點:增加的程式的擴充套件性,使得每次來一個例項化的物件,都是以同一種形式去呼叫的,多型性還增加了程式的可擴充套件性,通過繼承父類,減少了程式碼的冗餘
class Pig(Animal):
def speak(self):
print('哼哼哼')
pig = Pig()
pig.speak()
鴨子型別
上述例子,只要是動物就可以直接使用相同的方法!多型的存在其實也限制了子類的使用方法(抽象類也是可以限制子類),定義子類的時候,必須有speak()方法,這樣才能算的上動物類,所以python推薦使用“鴨子型別”,是一種不依賴於繼承,也可以實現不考慮物件型別而使用物件。
class People():
def speak(self):
print('啊啊啊')
class Pig():
def speak(self):
print('哼哼哼')
class Dog():
def speak(self):
print('汪汪汪')
def Speak(animal):
animal.speak()
peo = People()
pig = Pig()
dog = Dog()
Speak(peo)
Speak(pig)
Speak(dog)
# 結果
啊啊啊
哼哼哼
汪汪汪
父類限制子類的行為
- 抽象類 (abc模組)
- 繼承
主動報錯示例:
'''父類限制子類'''
class Txt():
# 父類限制子類必須實現的功能
def read(self):
raise Exception("是檔案就得有read功能")
class Conf(Txt):
pass
# 沒有實現read功能,繼承報錯
class Bin(Txt):
def read(self):
print('讀方法')
# conf = Conf()
# conf.read() # --->Exception: 是檔案就得有read功能
bin = Bin()
bin.read()
組合
類和類之間程式碼冗餘的問題可以通過繼承
來解決,或者super()
方法等,其實我們還可以通過組合
解決類與類之間程式碼冗餘的問題
組合:一個類中以另外一個類的物件作為資料屬性,就是類的組合,組合通常表示“有”的關係
class People():
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
class Course():
def __init__(self, name, period, price):
self.name = name
self.period = period
self.price = price
class Student(Course, People):
def __init__(self, name, age, gender, course=None):
if course is None:
course = []
self.courses = course
super().__init__(name, age, gender)
# 例項化學生物件
stu = Student('HammerZe', 18, 'male')
# 例項化課程物件
python = Course('python','6m',10000)
linux = Course('linux','5m',10000)
# 組合
stu.courses.append(python.name)
stu.courses.append(linux.name)
print(stu.courses)
# ['python', 'linux']
物件導向的內建函式
__init__()
:初始化方法__str__()
:列印物件的時候,自動觸發的函式__del__
():在物件被刪除的時候自動觸發__call__()
:物件加括號自動觸發__enter__()
:出現with語句,物件的__enter__
被觸發,有返回值則賦值給as宣告的變數__exit__()
:with中程式碼塊執行完畢時執行此方法
'''__str__() \ __del__() \ __call__()'''
class Foo():
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
'''輸出物件的時候列印,返回值只能是字串'''
def __str__(self):
return '輸出物件返回'
'''刪除物件的時候列印'''
# 1.刪除物件執行
# 2.如果不刪除物件,程式執行完畢也自動執行__del__()
def __del__(self):
print('刪除物件執行')
'''物件加括號自動觸發'''
def __call__(self, *args, **kwargs):
print('物件加括號自動觸發')
stu = Foo('HammerZe', 18, 'male')
print(stu) # --->輸出物件返回
del stu.name # --->刪除物件執行
stu() # --->物件加括號自動觸發
'''__enter__(),__exit__() '''
class Open():
def __init__(self,name):
self.name = name
def __enter__(self):
print('出現with語句,觸發此方法,如果該方法有返回值賦值給as後面的變數')
return 123
def __exit__(self, exc_type, exc_val, exc_tb):
print('with語句執行完畢觸發此方法')
with Open('a.txt') as f:
pass
print(f) # --->123
# --->出現with語句,觸發此方法,如果該方法有返回值賦值給as後面的變數
# --->with語句執行完畢觸發此方法
反射
hasattr(obj,pro)
:按pro判斷是否有無obj.pro屬性getattr(obj,pro,None)
:按pro判斷是否有無obj.pro屬性,沒有返回Nonesetattr(obj,pro,value)
:設定obj.pro的值相當於obj.pro = valuedelattr(obj,pro)
:刪除obj.pro
class Info():
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
oneself = Info('HammerZe', 18, 'male')
# 按字串查詢---hasattr
print(hasattr(oneself, 'name')) # --->True
print(hasattr(oneself, 'age')) # --->True
print(hasattr(oneself, 'gender')) # --->True
# 按字串查詢---getattr
print(getattr(oneself, 'name')) # --->HammerZe
print(getattr(oneself, 'age')) # --->18
print(getattr(oneself, 'gender')) # --->male
# 查詢不存在的
print(getattr(oneself, 'weight', None)) # --->None
'''None只是預設值,可以修改'''
print(getattr(oneself, 'weight', 140)) # --->140
# 按字串修改
setattr(oneself, 'name', 'li') # 相當於oneself.name = 'li'
print(oneself.name) # --->li
# 按字串刪除
delattr(oneself,'name') # 相當於del oneself.name
print(oneself.name) # --->AttributeError: 'Info' object has no attribute 'name'