亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Python面向對象,超類和抽象的概念是什么

發布時間:2022-01-17 17:23:49 來源:億速云 閱讀:238 作者:iii 欄目:互聯網科技

本文小編為大家詳細介紹“Python面向對象,超類和抽象的概念是什么”,內容詳細,步驟清晰,細節處理妥當,希望這篇“Python面向對象,超類和抽象的概念是什么”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。

對象魔法

在面向對象編程中,術語對象大致意味著一系列數據 (屬性) 以及一套訪問和操作這些數據的方法。

封裝

封裝講究結構復用,邏輯內斂,以固定接口對外提供服務。其遵循單一職責,規定每個類型僅有一個引發變化的原因。單一封裝的核心是解耦和內聚,這讓設計更簡單,清晰,代碼更易測試和凍結,避免了不確定性。

繼承

繼承在遵循原有設計和不改變既有代碼的前提下,添加新功能,或改進算法。其對應開閉原則,對修改封閉,對擴展開放。

多態

多態特性遵循里氏替換原則,所有繼承子類應該能直接用于引用父類的場合。

我們習慣于將復雜類型的公用部分剝離出來,形成穩固的抽象類。其他引發變化的相似因素則被分離成多個子類,以確保單一職責得到遵守,并能相互替換。

我們習慣于將復雜類型的公用部分剝離出來,形成穩固的抽象類。其他引發變化的相似因素則被分離成多個子類,以確保單一職責得到遵守,并能相互替換。

場景:先將整體框架抽象成基類,然后每個子類僅保留單一分支邏輯。

繼承和多態

定義一個名為 Animal 的 class,有一個 run() 方法可以直接打印:

class Animal(object):
  def run(self):
      print("Animal is running...")


當我們需要編寫 Dog 和 Cat 類時,就可以直接從 Animal 類繼承:

class Dog(Animal):
  pass
class Cat(Animal):
  pass

對于 Dog 來說,Animal 就是它的父類,對于 Animal 來說,Dog 就是它的子類。Cat 和 Dog 類似。

繼承的好處一:子類獲得了父類的全部功能,擴展子類自己的功能

上例中 Animial 實現了 run() 方法,因此,Dog 和 Cat 作為它的子類也擁有 run() 方法:

dog = Dog()
dog.run()

cat = Cat()
cat.run()

'''
Animal is running...
Animal is running...
'''


我們也可以擴展子類的方法,比如 Dog 類:

class Dog(Animal):
  def run(self):
      print("Dog is running...")
  def dog_eat(self):
      print("Eating bones...")


繼承的好處二:重寫父類的功能。

無論是 Dog 還是 Cat,它們 run() 的時候,顯示的都是 Animal is running...,而對于 Dog 和 Cat 本身,應該具有自己的 run() 特性,即: Dog is running..  和  Cat is running...,因此,對 Dog 和 Cat 類改進如下:

class Dog(Animal):
   def run(self):
       print("Dog is running...")
   def dog_eat(self):
       print("Eating bone...")

class Cat(Animal):
   def run(self):
       print("Cat is running...")
   def cat_eat(self):
       print("Eating fish...")

if __name__ == "__main__":
   dog = Dog()
   dog.run()

   cat = Cat()
   cat.run()
'''
Dog is running...
Eating bone...
Cat is running...
Eating fish...
'''


當子類的 run() 覆蓋了父類的 run() 時候,運行時總是會調用子類的 run() 。這樣,我們就獲得了繼承的另一個好處:多態。

判斷一個變量是否是某個類型可以用 isinstance() 判斷:

>>> isinstance(dog,Animal)
>>> isinstance(cat,Animal)
'''
True
True
'''

>>> isinstance(dog,Dog)
>>> isinstance(cat,Dog)
'''
True
False
'''


上面示例可以看到,dog 的數據類型既是 Animal,也是 Dog。因為 Dog 是從 Animal 繼承下來的,當我們創建 Dog 實例時,我們認為 dog 的數據類型是 Dog,但同時 dog 也是 animal 的數據類型,因為 Dog 本來就是 Animal  的一種。而 cat 的數據類型是 Animal 沒錯,但是 cat 不是 Dog 數據類型。

所以,在繼承關系中,如果一個實例的數據類型是某個子類,那它的數據類型也可以被看做是父類。但是,反過來就不行:

>>> b = Animal()
>>> isinstance(b, Dog)
'''
False
'''


Dog 可以看成 Animal,但 Animal 不可以看成Dog。

超類

要指定超類,可在 class 語句中的類名后加上超類名,并將其用圓括號括起。

Filter 是一個過濾序列的通用類。實際上,它不會過濾掉任何東西。

class Filter:
   def init(self):
       self.blocked = []
   def filter(self, sequence):
       return [x for x in sequence if x not in self.blocked]

class SPAMFilter(Filter):
   # SPAMFilter是Filter的子類 def init(self): # 重寫超類Filter的方法init
   def init(self): # 重寫超類Filter的方法init
       self.blocked = ['SPAM']
       
if __name__=="__main__":
   f = Filter()
   f.init()
   print(f.filter([1, 2, 3]))
   
'''
1, 2, 3
'''


Filter 類的用途在于可用作其他類 (如將 'SPAM' 從序列中過濾掉的 SPAMFilter 類) 的基類 (超類)。

if __name__=="__main__":
  s = SPAMFilter()
  s.init()
  a = s.filter(['SPAM', 'SPAM', 'SPAM', 'SPAM', 'eggs', 'bacon', 'SPAM'])
  print(a)
'''
['eggs', 'bacon']
'''


請注意 SPAMFilter 類的定義中有兩個要點。

  • 以提供新定義的方式重寫了 Filter 類中方法 init 的定義。

  • 直接從 Filter 類繼承了方法 filter 的定義,因此無需重新編寫其定義。

第二點說明了繼承很有用的原因:可以創建大量不同的過濾器類,它們都從 Filter 類派生而來,并且都使用已編寫好的方法 filter。

你可以用復數形式的 __ bases __ 來獲悉類的基類,而基類可能有多個。為說明如何繼承多個類,下面來創建幾個類。

class Calculator:
   def calculate(self, expression):
       self.value = eval(expression)
class Talker:
   def talk(self):
       print('Hi, my value is',self.value)
class TalkingCalculator(Calculator, Talker): pass

if __name__=="__main__":
   tc = TalkingCalculator()
   tc.calculate('1 + 2 * 3')
   tc.talk()
 
'''
Hi, my value is 7
'''

這被稱為多重繼承,是一個功能強大的工具。然而,除非萬不得已,否則應避免使用多重繼承,因為在有些情況下,它可能帶來意外的 “并發癥”。 

使用多重繼承時,有一點務必注意:如果多個超類以不同的方式實現了同一個方法 (即有多個同名方法),必須在class 語句中小心排列這些超類,因為位于前面的類的方法將覆蓋位于后面的類的方法。

因此,在前面的示例中,如果 Calculator 類包含方法 talk,那么這個方法將覆蓋 Talker 類的方法 talk (導致它不可訪問)。

如果像下面這樣反轉超類的排列順序:

class TalkingCalculator(Talker, Calculator): pass


將導致 Talker 的方法 talk 是可以訪問的。多個超類的超類相同時,查找特定方法或屬性時訪問超類的順序稱為方法解析順序 (MRO),它使用的算法非常復雜。

抽象基類

一般而言,抽象類是不能實例化的類,其職責是定義子類應實 現的一組抽象方法。

下面是一個簡單的示例:  

from abc import ABC, abstractmethod
class Talker(ABC):
  @abstractmethod
  def talk(self):
      pass


這里的要點是你使用 @abstractmethod 來將方法標記為抽象的 —— 在子類中必須實現的方法。

如果你使用的是較舊的 Python 版本,將無法在模塊 abc 中找到 ABC 類。在這種情況下,需要導入ABCMeta,并在類定義開頭包含代碼行 __ metaclass __ = ABCMeta (緊跟在 class 語句后面并縮進)。如果你使用的是 3.4 之前的 Python 3 版本,也可使用 Talker(metaclass=ABCMeta) 代替 Talker(ABC)。

抽象類(即包含抽象方法的類)最重要的特征是不能實例化。

>>> Talker()
  Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
 TypeError: Can't instantiate abstract class Talker with abstract methods talk


假設像下面這樣從它派生出一個子類:

class Knigget(Talker):
  pass


由于沒有重寫方法 talk,因此這個類也是抽象的,不能實例化。如果你試圖這樣做,將出現類似于前面的錯誤消息。然而,你可重新編寫這個類,使其實現要求的方法。

class Knigget(Talker):
  def talk(self):
      print("Ni!")


現在實例化它沒有任何問題。這是抽象基類的主要用途,而且只有在這種情形下使用 isinstance 才是妥當的:如果先檢查給定的實例確實是 Talker 對象,就能相信這個實例在需要的情況下有方法 talk。

>>> k = Knigget()
>>> isinstance(k, Talker) True
>>> k.talk()
Ni!

讀到這里,這篇“Python面向對象,超類和抽象的概念是什么”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

清新县| 麻江县| 临漳县| 全州县| 景泰县| 樟树市| 慈溪市| 淳安县| 海宁市| 大荔县| 峨眉山市| 安仁县| 栖霞市| 青冈县| 商南县| 兴安县| 高密市| 安泽县| 上林县| 仁怀市| 台北市| 南宫市| 额尔古纳市| 康马县| 靖远县| 磐石市| 常山县| 南乐县| 石门县| 四会市| 贵港市| 仪陇县| 勐海县| 南宁市| 郯城县| 浦江县| 桃园县| 西充县| 大新县| 洪泽县| 普格县|