日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python shape函数_Python中的多态及抽象类

發布時間:2024/7/23 python 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python shape函数_Python中的多态及抽象类 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本書同名免費MOOC《Python編程基礎及應用》在嗶哩嗶哩(B站)熱播,作者帶著你學。

版權聲明:本文內容引用自作者的圖書《Python編程基礎及應用》(高等教育出版社)。本文可以在互聯網上轉載傳播,但必須包含文中的版權聲明;本文不可以以紙質出版為目的進行摘抄或改編。

9.8 多態、抽象類

多態(polymorphism)是面向對象程序設計的一個重要概念,源自希臘語,意即“有多種形態”。對于程序設計而言,大致可以理解為:即使你不知道變量指向哪種形態,也能夠對其執行操作,而且操作的行為將隨對象的類型不同而不同。

對于Python程序員而言,可以不關心這個概念。因為在Python語言中,默認就是多態的。也就是說,對象被執行某個函數的時候,他的行為跟你想的多半是一樣的。但作者認為,讀者還是應該了解這個概念并理解其在程序設計中的重要性。

想象一個Word類軟件,WPS或者Open Office之類,在文檔中,用戶會加入非常多的界面元素,包括但不限于:三角形、箭頭、段落、圓形、矩形、藝術字、圖片。對,就跟你想的一樣,在面向對象程序設計中,這些元素都會使用類來描述,并且,設計者一定會為這些界面元素提供一個統一的父類。作者把這個類結構簡化成下圖的模樣,讀者要明白真實的情況比這個要復雜得多,但基本結構大體如此。

可以看到,所有的界面元素,三角形、圓形、... 、 文本段落(paragraph),被描述成擁有一個共同的祖先類-Shape。這個祖先類可以是抽象類,這意味著系統不允許你創建Shape類的對象,具體的稍后描述。抽象類什么具體的工作也不做,只是描述了他的全部后代的模樣:至少實現draw()-描繪自身以及getSize()-返回元素在頁面中的空間尺寸信息這兩個方法。這種描述是強制性的,它的后代必須實現這兩個方法或函數。

Triangle類用三個點坐標來描述自己的屬性,除了實現必須的draw()和getSize()方法外,還實現了一個getArea()方法以計算自身所占面積。

Circle類則用一個圓點坐標以及一個半徑來描述自己,也實現了額外的getArea()函數。

文本段落(Paragraph)類則用一個字符串sContent來存儲其文本內容,另外,還額外實現了setFont()函數來設置文本的字體和字體大小。

作者把這4個類組織一個程序文件里,命名Shapes.py。首先,我們定義抽象基類Shape。

#Shapes.pyfrom abc import ABC, abstractmethodclass Shape(ABC): @abstractmethod def draw(self): pass @abstractmethod def getSize(self): pass

首先,我們從abc模塊導入了ABC及abstractmethod。abc的意思作者猜應該是abstract base class - 抽象基類的首字母縮寫。Shape被描述成ABC的子類,draw()函數以及getSize()函數都打上了@abstractmethod裝飾符,這說明這兩個函數為抽象函數。這種情況下,系統是不允許創建一個Shape對象的。這個抽象類存在的唯一意義就是規定了它的后代類的某些特征:必須實現 draw()及getSize()方法。

如果嘗試實例化Shape, 比如s = Shape(),就會得到下述錯誤信息:

Traceback (most recent call last): File "D:/pylearn/C9_OOP/Shapes.py", line 11, in s = Shape()TypeError: Can't instantiate abstract class Shape with abstract methods draw, getSize

當且僅當Shape的某個后代類定義實現了Shape的全部抽象函數,該類才可以被實例化 - 即允許創建該類型的對象。下面是Triangle類、Circle類、Paragraph類的極簡版本代碼,注意,連同Shape類,這4個類都在同一個py文件中。

#Shapes.py...class Triangle(Shape): def __init__(self): self.point0 = (0,0) self.point1 = (0,0) self.point2 = (0,0) def draw(self): print("Triangle::draw") def getSize(self): pass #detail omitted def getArea(self): return 0 #it should be w * h / 2#Shapes.py...class Circle(Shape): def __init__(self): self.ptCenter = (0,0) self.iRadius = 0 def draw(self): print("Circle::draw") def getSize(self): pass def getArea(self): return 0#Shapes.py...class Paragraph(Shape): def __init__(self): self.sContent = "" def draw(self): print("Paragraph::draw") def getSize(self): pass def setFont(self,fontName,fontSize): pass

這三個類都實現了Shape抽象基類的全部抽象方法,都不再“抽象”,可以實例化。另外,我們還注意到這三個類的構造函數里都沒有調用執行Shape類的構造函數,這里這樣做是可以的,因為Shape類沒有自定義構造函數,或者說Shape類的構造函數什么也沒做。

讓我們把關注點放在這三個類的draw()函數上。Office類軟件會用文檔來組織這些界面元素,在這里我們把這些界面元素想像成一個列表,在這個列表里包含了很多個三角形、矩形、段落、圖片、藝術字、公式、圖表對象,這些對象都是Shape類的子對象,都實現了draw()方法。

當一個頁面被顯示出來時,軟件會遍歷這個列表,然后逐一調用列表內Shape子對象的draw()方法,以便把每個界面元素畫出來。對,你聽得沒錯,就是每個對象自己畫自己。因為三角形類了解三角形的數據表達形式,掌握描繪一個三角形的全部信息,由這個類的draw()來承擔這個職責再合適不過了。圓形、段落這些類也是類似情況。我們設想一下,假設在頁面上描繪三角形的任務不是由三角形類來完成,而是由外部代碼來完成,那么外部代碼就必須清楚并訪問三角形對象內部的全部細節,如果這件事情真的發生的話,對于軟件工程而言是災難性的:外部代碼知道太多關于三角形內部實現的細節! 內部實現的細節變成了接口的一部分! 三角形類接口不再簡潔明了! 以后你如果想修改三角形的內部數據結構,這幾乎不可能,因為外部代碼也要跟著改,涉及的外部程序和修改點可能太多 --- 這種復雜的情況,我們稱之為緊耦合 - tight coupling。而程序的松散耦合 - loose coupling,才是我們的目標。

#Shapes.py...t1 = Triangle()t2 = Triangle()c1 = Circle()c2 = Circle()p1 = Paragraph()#doc模擬一個文檔,將界面元素組織在列表中doc = [p1,c2,t2,c1,t1]#遍歷全部界面元素,將它們全部畫出來def renderDocument(doc): for x in doc: x.draw()renderDocument(doc)

執行結果

Paragraph::drawCircle::drawTriangle::drawCircle::drawTriangle::draw

在這段代碼里,我們創建了兩個三角形,兩個圓形,一個段落 ,然后把它們放入一個列表中,這個列表就是一個文檔的簡化表達形式。renderDocument()函數遍歷這個列表,逐一執行其元素的draw()方法。我們看到,renderDocument()函數并不清楚變量x的具體類型,它只認為x是一個Shape,實現了draw()方法,至于x到底是三角形、圓形或者別的什么界面元素,完全不關心。但是,我們發現,x是什么類型,就會執行什么類型的對應的draw()函數,并打印出對應的文字。這就是多態,這些變量類型未知,但自動展現出與類型對應的恰當行為。

作為初學者的你,看見這個覺得平淡無奇: 這不就是我想像的樣子么! 是的,這正好說明Python語言的設計目標達到了,它幾乎總是按你的設想來工作。但這樣做是有代價的,代價之一就是執行效率低。在C++這種講究效率的語言里,為了追求效率,多態不是默認的。

本節展示的類結構為程序的擴展提供了無限的可能及便利。如果Office軟件試圖建立一種全新的界面元素,比如某種直方圖圖表,軟件設計者所要做的,就是繼承Shape類并設計一個新的類,然后在新的類里實現全部抽象函數。然后,上述renderDocument()函數一個字符都不用修改,即可以擁抱新的界面元素的加入所帶來的變化,以不變應萬變!

總結

以上是生活随笔為你收集整理的python shape函数_Python中的多态及抽象类的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。