python 多型、組合、反射

HammerZe發表於2021-12-07

多型、多型性

多型

多型通俗理解起來,就像迪迦奧特曼有三種形態一樣,怎麼變還是迪迦奧特曼

image

  • 定義:多型指的是一類事物有多種形態

示例如下:
image

'''動物有多種表現形態,人也是動物之一,在這裡會說話就是動物'''
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()

鴨子型別


image


上述例子,只要是動物就可以直接使用相同的方法!多型的存在其實也限制了子類的使用方法(抽象類也是可以限制子類),定義子類的時候,必須有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)

# 結果
啊啊啊
哼哼哼
汪汪汪

父類限制子類的行為

image


  • 抽象類 (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語句執行完畢觸發此方法

反射


image


  • hasattr(obj,pro):按pro判斷是否有無obj.pro屬性
  • getattr(obj,pro,None):按pro判斷是否有無obj.pro屬性,沒有返回None
  • setattr(obj,pro,value):設定obj.pro的值相當於obj.pro = value
  • delattr(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'

image

相關文章