# Python 類別的定義與使用 - Class Attributes ###### tags: `python` [參考課程](https://www.brilliantcode.net/761/python-3-6-class/?cli_action=1599055378.214) [參考影音課程](https://www.youtube.com/watch?v=uPKgQ3FoVtY) 物件導向的三大特性:封裝、繼承、多型 > Class繼承、多型、封裝、建構子、變數、父類別的屬性/方法 * 語法 ```python= class FirstClass: #定義類別 """My first class in python.""" str = "Apple" #定義變數 def fun(self): # 在類別內的函數都至少要傳入參數self return "Hello world." my_obj = FirstClass() # 宣告一個類別為FirstClass的物件 print(my_obj.str) # 使用物件的公開變數 print(my_obj.fun()) # 使用物件的公開函數 ``` 定義類別 說明:類別(class)下可以有變數屬性、函式屬性 用法: (1)類別與類別屬性 (類別名稱.屬性名稱) (2)類別與實體物件、實體屬性 (實體物件名稱.實體屬性名稱) --- 1. 建構子 參數固定放入self,透過self來操作實體物件,建立實體物件時,不必特別寫self ```python= def __init__(self, 其他參數): ``` >Python不支援多建構子(multi constructor),但是可以透過預設值的方式來達成 ```python= def __init__(self, para1=”para1預設值”, para2=”para2預設值2″): ``` 上述方法即可以有3種宣告方式 >使用類別自己的變數、函數都須要加上『 self.變數名稱 』才能使用 範例1: ```python= class Point: def __init__(self): self.x = 3 self.y = 4 def show(self): #self一定要寫,代表實體物件本身 print(self.x,self.y) def distance(self,targetX,targetY): return ((self.x-targetX)**2)+((self.y-targetY)) #建立實體物件 #此實體物件包含x和y兩個實體屬性 p=Point(1,5) #1放入x,5放入y print(p.x+p.y) p.show()#呼叫實體方法/函式 p.distance(0,0)#計算座標3,4和坐標0,0的距離 ``` 範例2: ```python= class FirstClass: """My first class in python.""" str1 = "Apple" str2 = "IBM" def __init__(self, str1="參數1", str2="參數2"): self.str1 = str1 self.str2 = str2 def fun(self): return "Hello world." my_obj = FirstClass() print(my_obj.str1) print(my_obj.str2) print("===分隔線===") my_obj2 = FirstClass("我是參數1") print(my_obj2.str1) print(my_obj2.str2) print("===分隔線===") my_obj3 = FirstClass("我是參數1", "我是參數2") print(my_obj3.str1) print(my_obj3.str2) ``` 印出: >參數1 參數2 ===分隔線=== 我是參數1 參數2 ===分隔線=== 我是參數1 我是參數2 --- 2. 繼承 語法: ```python= class 類別名稱(父類別): ``` 範例: ```python= class Car: wheels_number = 4 # 輪胎數量 car_doors = 4 # 車門數量 passengers = 4 # 乘客數量 def __init__(self, wheels_number=4, car_doors=4, passengers=4): self.wheels_number = wheels_number self.car_doors = car_doors self.passengers = passengers # SUV也是一種車子,所以繼承Car class SUV(Car): brand_name = "" # 品牌名稱 air_bag = 2 # 安全氣囊數 sunroof = True # 是否擁有天窗 def __init__(self, wheels_number, car_doors, passengers, brand_name="", air_bag=2, sunroof=False): super().__init__(wheels_number, car_doors, passengers) self.brand_name = brand_name self.air_bag = air_bag self.sunroof = sunroof def getDetails(self): print("==== Details ====") print("Brand:", self.brand_name) print("Wheels number:", self.wheels_number) # 可直接呼叫父類別的變數(屬性) print("Doors number:", self.car_doors) # 可直接呼叫父類別的變數(屬性) print("Air-bags number:", self.air_bag) print("Sunroof:", self.sunroof) print("=================") # 宣告一台Toyota RAV的休旅車(SUV) toyota_rav = SUV(4, 5, 5, "Toyota RAV", 4, True) toyota_rav.getDetails() # 宣告一台BMW X5的休旅車 bmw_x5 = SUV(4, 5, 5, "BMW X5", 6, True) bmw_x5.getDetails() ``` --- 3. 多型 >不同型態的物件,定義相同的操作介面,由於被呼叫者 (Callee) 有著相同的介面,呼叫者並不用指定特別型別,只需針對介面進行操作。 >定義兩種繼承Car的類別(SUV, Bus),同時也直接覆載(overwrite)父類別已經定義的方法 撰寫方法:直接在子類別中覆載覆類別的方法即可 ```python= class Car: # wheels_number:輪胎數量, car_doors:車門數量, passengers:乘客數量 def __init__(self, wheels_number=4, car_doors=4, passengers=4): self.wheels_number = wheels_number self.car_doors = car_doors self.passengers = passengers def drive(self): print("Drive a car.") # SUV也是一種車子,所以繼承Car class SUV(Car): # brand_name:品牌名稱, air_bag:安全氣囊數, sunroof:是否擁有天窗 def __init__(self, wheels_number, car_doors, passengers, brand_name="", air_bag=2, sunroof=False): super().__init__(wheels_number, car_doors, passengers) self.brand_name = brand_name self.air_bag = air_bag self.sunroof = sunroof # 覆寫父類別的drive def drive(self): print("Drive this {0} to my vacation.".format(self.brand_name)) def getDetails(self): print("==== Details ====") print("Brand:", self.brand_name) print("Wheels number:", self.wheels_number) # 可直接呼叫父類別的變數(屬性) print("Doors number:", self.car_doors) # 可直接呼叫父類別的變數(屬性) print("Air-bags number:", self.air_bag) print("Sunroof:", self.sunroof) print("=================") # Bus也是一種車子,所以繼承Car class Bus(Car): # brand_name:品牌名稱, air_bag:安全氣囊數, sunroof:是否擁有天窗 def __init__(self, wheels_number, car_doors, passengers, brand_name="", air_bag=0): super().__init__(wheels_number, car_doors, passengers) self.brand_name = brand_name self.air_bag = air_bag # 覆寫父類別的drive def drive(self): print("Take this {0} to my vacation.".format(self.brand_name)) def getDetails(self): print("==== Details ====") print("Brand:", self.brand_name) print("Wheels number:", self.wheels_number) # 可直接呼叫父類別的變數(屬性) print("Doors number:", self.car_doors) # 可直接呼叫父類別的變數(屬性) print("Air-bags number:", self.air_bag) print("=================") # 宣告一台Toyota RAV的休旅車(SUV) toyota_rav = SUV(4, 5, 5, "Toyota RAV", 4, True) # 宣告一台BMW X5的休旅車 bmw_x5 = SUV(4, 5, 5, "BMW X5", 6, True) # 宣告一台Volvo Bus的巴士 volvo_bus = Bus(4, 3, 50, "Volvo Bus", 0) # 分別呼叫各種車輛的drive()方法 def letsDrive(cars): for car in cars: car.drive() letsDrive([toyota_rav, bmw_x5, volvo_bus]) ```