跳到主要內容

Python筆記(11)-類別與物件

Python筆記(11)-類別與物件

這個章節要介紹類別與物件的概念,舉個例子:一個實體的"人"他可能屬於男生,也可能屬於女生,這種性別的概念我們稱為這個實體的"人"的特徵。另外,一個實體的"人"會"說話","說話"我們稱為這個實體的人的行為。從上面的例子,實體的"人"稱為物件,"人"稱為類別,而"人"的特徵跟行為我們稱為屬性(attribute)和方法(method),換句話說,類別是個抽象的概念,是用來定義一個物件該有的屬性(attribute)和方法(method),而物件則是類別實體化(instance)

使用類別概念撰寫程式可以讓我們建立更具有結構性和可維護性的程式碼,同時也能夠提高程式碼的可重用性和擴展性。

類別具有封裝(encapsulation)、繼承(inheritance)、多型(polymorpgism)特性,我們以下會使用簡單的例子說明封裝、繼承、多型的概念與用法。

11.1 類別的程式基本架構與封裝

我們說過類別是用來定義物件的屬性與方法,所以我們必須了解程式結構中哪個地方是設定屬性,哪個地方是設定方法,請看以下範例:

以上是一個動物的類別,__init__()Python中的一個特殊方法,也稱為構造函數或初始化方法。它在建立新的物件時自動呼叫,並用於設置物件的屬性。在__init__()self是必要的且必須放在最前面,他代表被建立的物件,self後面放的參數就是屬性,以上面的例子,n就是代表名字的屬性,也就是說我們建立一個實體動物物件時,我們有一個參數可以輸入,而這個參數代表幫這個動物物件取的名字,而我們可以用物件.name的方式知道該動物物件的名字。sing(self)代表另一個方法,是我們為這個動物類別定義的一個方法(唱歌的行為),代表動物類別產生的物件都會這個行為,我們可以使用物件.sing()的方式使這個物件執行這個行為。以下是執行的範例:

我們再給一個比較複雜的例子,當中有兩個屬性(name,age),兩個方法(grow(),sing()),其中grow()的方法是可以讓物件的年紀成長的功能。

對於屬性值我們可以設定公用屬性或者私用屬性,公用屬性代表可以在物件建立後還可以直接修改,如果是私用屬性,則在物件建立後無法再修改屬性值。

以上的範例中,name的屬性就是公用屬性,所以當Bird=Animal("小鳥",1)被執行,代表Bird這個物件他的名字叫小鳥,使用Bird.name即可得知。但如果我們執行Bird.name="麻雀",此時Bird這個物件他的名字就被改成麻雀了。請參考以下結果。

這時候我們就會繼續往下追問,私有屬性該如何設定,其實就是將self.name改成self.__name,此時一旦物件建立後無法再修改屬性值。請參考以下範例。

雖然私用屬性無法在物件建立後直接修改,但我們可以在類別定義一個修改名字的方法,利用呼叫這個方法來改名字,如上述程式碼中rename(self,rename)方法,請參考以下程式執行結果。

有私有屬性當然也會有私有方法,請看以下程式內容:


以上__grow()就是私有方法,在物件建立後就無法使用了,所以就沒有讓物件的年紀成長。但述如果還是想要有這個功能的話,除了改為公用方法外,就是在定義一個方法去呼叫__grow()進而達到年紀成長的功能,也就是上述程式碼中的grow2()方法。以上這種在類別中使用私有屬性與私有方法的概念就稱為封裝。

11.2 繼承

如有有一個類別A可以延續使用類別B所定義的屬性與方法,我們就稱類別A是類別B的子類別(child class),而類別B稱為父類別(parent class)。這樣類別的設計概念就稱為繼承。我們用以下的例子說明類別繼承的程式基本架構:

以上的例子,我們一開始先建立Animal的類別,在裡面的定義了兩個屬性,三個方法。接下來我們見了一個Animal的一個子類別Bird(Animal),在Bird(Animal)類別中的定義了name,age,specy三個屬性,其中name,age這兩個屬性在Animal類別中有被定義,所以可以被繼承下來,要繼承父類別的屬性,就必須在__init__()前面加上super(),也就是super().__init__(self,name,age)這種寫法,但specy這個屬性在父類別中沒有被定義,所以無法使用繼承。

由程式執行的結果可以看到,Bird(Animal)類別中我們沒有定義sing()的方法,但他仍舊可以使用Animal類別中sing()的方法,這就是因為繼承帶來的好處。

我們再來看一個例子,這個例子我們在父類別與子類別都定義了想同的方法sing(),這時候子類別如果要呼叫sing()方法,此時會執行子類別中的sing()方法,而不會執行父類別的sing()。另外,我們在這個例子中特意在父類別中把age設計成私有屬性,就我們之前所說的,私有屬性在物件建立後是不能被修改的,無法直接被呼叫,所以在子類別要使用self.__age來取得age是無法的,所以我們在父類別建立一個取得age的方法getAge()方法且用return的方式回傳self.__age值,而這樣子類別就可以使用getAge()方法來取得age

11.3 多型

多型是指多個類別(不一定要有父子類別的關係)可以具有共同的方法名稱,

而且可以有不同的功能,我們用以下的例子作為說明:

我們建立了3個類別,Animal(), Plane(), Bird(Animal)這三個類別都有定義fly()方法且內容都不一樣,這就是多型的概念。

三個物件同時呼叫相同fly()方法,但是輸出結果不同。

11.4 多重繼承

一個子類別可以繼承多個父類別,這種概念就叫做多重繼承。如果父類別有相同的屬性或方法的話,則會從同一階層的父類別由左至右搜尋。我們用以下的例子進行說明:


Child類別是FatherMother類別的子類別且這個類別沒有定義任何屬性與方法,此時Child要呼叫say()方法時,輸出結果會是Father中定義的say()方法,因為FatherMother類別都有say()方法且位於同一階層的父類別又程式會從左邊開始搜尋say()方法,故會先找到Father中定義的say()方法。

11.5 類別的簡單範例

我們定義RetangleTriangle兩個類別,其中TriangleRetangle的子類別,Retangle中定義了兩個屬性(長與寬),方法(面積與周長)Triangle繼承了Retangle兩個屬性並增加一個屬性(三邊長),與Retangle有相同的方法,但內容截然不同。

留言

這個網誌中的熱門文章

RPA-Uipath筆記(1) - 如何從網路上下載資料並存至指定路徑

最近在做 RPA 相關專案時遇到了這個問題: 如何從網路上下載資料並存至指定路徑? 針對這個問題我們採取的解決方案是 先讓檔案下載到電腦的預設路徑,再將檔案移動到我們指定的資料夾 。 以下我們用下載政府公開資料平台的資料 ("https://data.gov.tw/dataset/116285") 為例, Uipath 的流程建立如下: 使用到了 Wait for Download 、 Move File 、 Delete File 三個 Activity , Wait for Download 中 Monitored folder 必須放瀏覽器中設定的下載檔案的預設路徑且關閉詢問儲存位置。 Downloaded file 則是設定一個變數名稱 downloadfile( 可自訂 ) ,此變數的資料型態是 FileInfo 。中間則放入下載的流程步驟,從下載開始到結束都會在此 Activity 中執行完畢,執行完後所下載的檔案的相關資訊都會被存放在變數 downloadfile 中。 接下來是將檔案從預設下載路徑中移至指定路徑,這裡就需要下載預設路徑與指定路徑,這兩個我們在流程一開始就建了了兩個變數 dnlo_path 、 asng_path ,寫法如下: dnlo_path = "C:\Users\" +system.Environment.UserName+ "\Downloads" system.Environment.UserName à VB 語法,代表目前電腦的使用者名稱。 asng_path = "D:\Bolg 資料 \Uipath\Uipath(1)" Move File Activity 中 From 要放入目前檔案的位置; To 則要放入檔案存放的指定的位置,但因為是要做檔案的移動,所以以上兩個路徑後面都要再加上檔案名稱,這時可以使用 downloadfile 這個變數的屬性值叫出檔案名稱( downloadfile.Name ),當檔案名稱是隨機變動的時候,非常好用。另外,特別值得注意的是, To 的部分在加上檔案名稱時,可以不用用原始檔案的名稱,這時可以同時達到修改檔名的效果。 Overwrite 的部分打勾代表再重複執行一次的時...

RPA-Uipath(2) - 字串分割(String.Split())與合併(String.join())

在資料清理中,我們常常需要對字串進行分割或合併,今天來簡單介紹 Uipath 中字串如何進行分割與合併。 1.      字串分隔 ( 單一分割符號 ) 我們首先建了一個字串變數 Str1= "Jimmy,Johnson,Shawn,Alan,Nick" ,我們現在想把這些人名一個一個切割出來,很明顯只要將 ”,” 作為分個符號就可以了。這邊我們建立一個陣列變數 Str1_Array=Str1.split(","c) ,這個陣列變數就會儲存分割出來的結果。我們接下來用 For each 與 Write Line 將陣列的每一項內容印出來,就可以知道我們分割的結果有沒有成功。 2.      字串分隔 ( 多個分割符號 ) 我們首先建了一個字串變數 Str2= "Jimmy,Johnson.Shawn Alan,Nick" ,我們現在想把這些人名一個一個切割出來,很明顯要將 ”,” 、 ”.” 、 ” “ 都作為分個符號才能完整分割。這邊我們建立一個陣列變數 Str2_Array= Str2.Split(",|.| ".ToArray()) or Str2.Split({","c,"."c," "c}) ,這個陣列變數就會儲存分割出來的結果。我們接下來用 For each 與 Write Line 將陣列的每一項內容印出來,就可以知道我們分割的結果有沒有成功。 3       字串的合併 (Array 字串元素合併 ) 我們首先建了一個字串變數 Str3_Array= {"John","Jimmy","Shawn","Alan"} ,我們現在想把這些人名中間用 ”|” 符號隔開並且變成一個字串,這裡我們是用 String.Join( 連接符號 , 陣列 ) 這個函數達到這個目的。我們建立一個變數 Str3_Join ,使 Str3_Join=String.Join("|", Str3_Array) ,此時 Str3_Join 的結果就會是 John|Jimmy|Shawn|Alan 。我們接下來用 Write...

RPA-Uipath(5)-如何讀取Mail與取得Mail的資訊

本篇主要介紹 Uipath 取得 mail 相關資訊與附件的方法,因為 mail 的種類眾多,本範例以 Gmail 為例。首先在使用 Uipath 取得 Gmail 相關資訊前須對 Google 帳戶的安全性進行兩階段驗證設定,設定方式如下: Step1. 點選 ” 管理你的 Google 帳戶 ” Step2.  點選 ” 安全性 ” à ” 兩階段驗證 ” à 點選 ” 開始使用 ” Step3.  依 Google 所提示步驟,您最後會取得一組密碼,請務必將此密碼記下。 接下來要開始使用 Uipath 擷取 mail 相關資訊,一開始我們先使用 Get Password 儲存 mail 登入的密碼,此時密碼不是使用您真正的密碼而是使用剛剛兩階段驗證後取得的密碼,並儲存於變數 password 。 接下來使用 Get IMAP Mail Messages 來取得 mail 的相關資訊,在使用 Get IMAP Mail Messages 時必須在其屬性設定區塊進行一些參數設定。 Port 欄位填入 993 , Server 欄位填入 "imap.gmail.com" , Email 欄位填入您的 Email , Password 欄位填入 變數 password , Message 欄位我們用 MailMessage 變數填入 Mail 的相關資訊都會存在 MailMessage 變數中,我們可以用 For Each 迴圈逐一取得 mail 的相關資訊。 For Each 的屬性區塊部分也需要進行一些參數設定, List of item 欄位需填入 MailMessage 變數, TypeArgument 則須設定為 System.Net.Mail.MailMessage 。 設定完成後,我們先用 Write Line 將信件的主旨印出做為測試( 這邊我們只印出前 5 封信件的主旨,可在 Get IMAP Mail Messages 的屬性區塊中 Top 欄位中設定 ),如果要印出信件主旨,需要用 item.Subject 屬性,如要印出其他資訊,我們將常用的幾個列在以下表格: 最後,有些信件會附帶一些附件,我們如何將這些物件儲存下來呢 ? 這邊只需要用到 Save Attachments 即可。我們將其放在迴圈內以下載每個有附件的 mail...