iT邦幫忙

2021 iThome 鐵人賽

DAY 5
0
自我挑戰組

終極大數據地獄系列 第 5

#5 Python進階教學2

類別

  • 類別裡封裝了變數和函數
  • 被封裝在類別裡的變數稱為屬性
  • 被封裝在類別裡的函數稱為方法(方式、功能)
  • 先定義類別,才能使用類別中封裝起來的變數和函數
  • 具有封裝、繼承、多型特性

類別就是自訂的資料型態先定義類別,才能使用類別中封裝起來的變數和函數

# 定義類別
class 類別名稱():
    變數a
    變數b
    
# 使用類別
# 建立物件,把類別的結構放到變數裡,變成物件
變數1 = 類別名稱()
變數2 = 類別名稱()

# 操作物件裡的內容
變數1.變數a = 數值X
變數2.變數a = 數值Y
print(變數1.變數a)

程式碼

# 定義類別
class Car():
    color = ""
    brand = ""
    
# 使用類別
if __name__ == "__main__":
    # 建立物件,把類別放到變數裡,變成物件
    porsche = Car()
    benz = Car()
    # 操作物件裡面的內容(屬性)
    porsche.color = "白"
    porsche.brand = "保時捷"
    benz.color = "黑"
    benz.brand = "賓士"
    print(porsche.color, porsche.brand)
    # 印出 白 保時捷
    print(benz.color, benz.brand)
    # 印出 黑 賓士

初始化副程式,俗稱建構子,初始化副程式的名稱一律為__init__,如果副程式會程式會使用該類別內的其他變數或副程式,那麼在宣告副程式時,就必須在參數內加入一個self參數,副程式就可以使用self參數操作到同個類別內其他的變數或副程式,用法如下

# 定義類別
class 類別名稱():
    變數a
    變數b
    
    def __init__(self, 參數...):
        初始化副程式區塊...
    
    def 副程式a(self, 參數...):
        副程式區塊...
        return 傳回值
    
# 使用類別
# 建立物件,把類別放到變數裡,變成物件(使用時不用加self)
變數1 = 類別名稱(參數...)
變數2 = 類別名稱(參數...)

# 操作物件裡的內容
變數1.變數a = 數值X
變數2.變數a = 數值Y
print(變數1.變數a)

print(變數2.副程式a(參數...))

程式碼示範

# 定義類別
class Car():
    color = ""
    brand = ""
    # 定義初始化副程式
    def __init__(self, c, b):
        self.color = c
        self.brand = b
        print("新車建構完成,"+self.milage(0))

    def milage(self, km):
        return "里程數為"+str(km)+"公里"

# 使用類別
if __name__ == "__main__":
    # 建立物件,把類別放到變數裡,變成物件,並執行初始化副程式(加入初始值時不用加self)
    porsche = Car("白", "保時捷")  
    # 印出 新車建構完成,里程數為0公里    
    print(porsche.milage(1000))
    # 印出 里程數為1000公里   

物件導向程式設計有三大特性:

  • 繼承
  • 封裝
  • 多形

繼承

繼承就是以一個既有的類別,對那個類別進行擴充,變成一個新的類別,這個就叫繼承,原有的類別稱為父類別,以父類別為基礎做擴充跟改寫而成的新類別稱為子類別, 在擴充父類別時如果定義新的變數或是副程式,名稱跟原本父類別一樣的話,將以子類別的為主,這時候就會產生一個問題,若新增在子類別的變數需要再初始化函數時做操作,該怎麼辦呢?如果直接寫一個新的__init__初始化副程式,就會取代掉原本父類別的初始化副程式了,當然可以直接重寫__init__初始化副程式,可是當父類別太龐大時就會很麻煩,因有我們有個方便的解決方法,那就是supersuper可以直接將父類別的初始化副程式保留下來,讓我們可以以這為基礎進行初始化副程式的改寫,這種方式不但繼承了類別的結構,連初始化的方式也一並繼承下來,可謂真正的物件導向繼承的特色阿,以下直接以程式碼示範

# 定義類別,此類別在本範例中當成父類別
class 類別名稱A:
    變數A(屬性)
    
    def __init__(self, 參數1, 參數...):
        初始化副程式區塊...
        
    def 副程式A(self, 參數...):
        副程式(方法)區塊...
        
# 定義類別,此類別為子類別,以上面的類別最為父類別來繼承,以上面類別為基礎做擴充改寫
class 類別名稱B(類別名稱A):
    # 新增一個屬性,變數B
    變數B(屬性)
    
    #定義初始化副程式,將使用super(),繼承父類別的初始化副程式
    def __init__(self, 父類別原有的參數..., 子類別新增的參數...):
        # super()可以直接將父類別的初始化副程式保留下來
        # 下面這行可以視為保留父類別原有的初始化副程式程式區塊
        super(類別名稱B, self).__init__(父類別原有的參數...)
        # 以下是繼承後新增的程式碼
        新增的初始化副程式區塊...
    
    # 新增一個方法,副程式B
    def 副程式B(self, 參數...):
        副程式(方法)區塊...

範例

# 定義類別,此類別在本範例中當成父類別
class Car():
    color = ""
    brand = ""

    def __init__(self, c, b):
        self.color = c
        self.brand = b
        print("新車建構完成,"+self.milage(0))

    def milage(self, km):
        return "里程數為"+str(km)+"公里"

# 定義類別,此類別為子類別,以上面的類別最為父類別來繼承,以上面類別為基礎做擴充改寫
class Taxi(Car):
    # 新增一個屬性,司機 driver
    driver = ""
    
    #定義初始化副程式,將使用super(),繼承父類別的初始化副程式
    def __init__(self, c, b, d):
        # super()可以直接將父類別的初始化副程式保留下來
        # 下面這行可以視為保留父類別原有的初始化副程式程式區塊
        super(Taxi, self).__init__(c, b)
        # 以下是繼承後新增的程式碼
        self.driver = d

    # 新增一個方法,傳回牌照種類,副程式licensePlate
    def licensePlate(self):
        return "營業用牌照"

if __name__ == "__main__":
    uber = Taxi("白", "保時捷", "韓總雞")  
    # 印出 新車建構完成,里程數為0公里
    print(uber.milage(1000))
    # 印出 里程數為1000公里
    print(uber.driver)
    # 印出 韓總雞
    print(uber.licensePlate())
    # 印出 營業用牌照

封裝

簡單來說,你不需要知道類別裡面是如何設計的,你只要會使用就好,就像一台手機,內部零件五花八門,但你不需要懂零件,只要會用就好,零件都被封裝起來一般,類別裡不想要被存取變數和副程式,就是需要被封裝起來的成員,稱為私有成員,作法很簡單,只要在變數或副程式的名稱前加上__,該變數或副程式就會被封裝起來了,爾後在操作時,只要試圖存取被封裝的私有成員,都是不允許的,範例如下

class 類別名稱:
    變數A(屬性)
    #定義私有成員變數B
    __變數B(屬性)
    
    def 副程式A(self, 參數...):
        副程式(方法)區塊...
    #定義私有成員副程式B   
    def __副程式B(self, 參數...):
        副程式(方法)區塊...

程式碼 圓面積計算器

class Area():
    r = 0
    # 定義私有成員__pi
    __pi = 3.14

    def __init__(self, r):
        self.r = r
        print("面積為" + str(self.__area()))
        
    # 定義私有成員__area()
    def __area(self):
        return self.r ** 2 * self.__pi


if __name__ == "__main__":
    o = Area(6)  
    #印出 面積為113.04
    print(o.r)
    #印出  6
    print(o.__pi)
    #私有成員,無法存取所以會報錯 

多形

意思就是呼叫同樣名稱的方法時,會得到不同的結果,python會根據呼叫的類別來決定要執行哪個副程式,這就是多型

class Thor():
    def cast(self):
        print("Chris Hemsworth")

class CaptainAmerica():
    def cast(self):
        print("Chris Evans")

class StarLord():
    def cast(self):
        print("Chris Pratt")

if __name__ == "__main__":
    Chris1 = Thor()
    Chris2 = CaptainAmerica()
    Chris3 = StarLord()
    Chris1.cast()
    #印出 Chris Hemsworth
    Chris2.cast()
    #印出 Chris Evans
    Chris3.cast()
    #印出 Chris Pratt

上一篇
#4 Python進階教學1
下一篇
#6 Python進階教學3
系列文
終極大數據地獄24

尚未有邦友留言

立即登入留言