創建Dog類
根據Dog 類創建的每個實例都將存儲名字和年齡。我們賦予了每條小狗蹲下(sit() )和打滾(roll_over() )的能力:
1 class Dog(): 2 '''一次模擬小狗的簡單嘗試''' 3 4 def __init__(self, name, age): 5 """初始化屬性name和age""" 6 self.name = name 7 self.age = age 8 9 def sit(self): 10 """模擬小狗被命令時蹲下""" 11 print(self.name.title() + " is now sitting.") 12 13 def roll_over(self): 14 """模擬小狗被命令時打滾""" 15 print(self.name.title() + " rolled over!") 16
根據類創建實例
1 class Dog(): 2 '''一次模擬小狗的簡單嘗試''' 3 4 def __init__(self, name, age): 5 """初始化屬性name和age""" 6 self.name = name 7 self.age = age 8 9 def sit(self): 10 """模擬小狗被命令時蹲下""" 11 print(self.name.title() + " is now sitting.") 12 13 def roll_over(self): 14 """模擬小狗被命令時打滾""" 15 print(self.name.title() + " rolled over!") 16 17 my_dog = Dog('willie', 6) 18 your_dog = Dog('lucy', 3) # 創建多個實例 19 20 print("My dog's name is " + my_dog.name.title() + ".") # my_dog.name 訪問屬性 21 print("My dog is " + str(my_dog.age) + " years old.") 22 my_dog.sit() # 調用方法 23 my_dog.roll_over() 24 25 print("\nYour dog's name is " + your_dog.name.title() + ".") 26 print("Your dog is " + str(your_dog.age) + " years old.") 27 your_dog.sit()
運行結果
My dog's name is Willie. My dog is 6 years old. Willie is now sitting. Willie rolled over! Your dog's name is Lucy. Your dog is 3 years old. Lucy is now sitting. Process finished with exit code 0
使用類和實例
Car類
1 class Car(): 2 """一次模擬汽車的簡單嘗試""" 3 4 def __init__(self, make, model, year): 5 """初始化描述汽車的屬性""" 6 self.make = make 7 self.model = model 8 self.year = year 9 self.odometer_reading = 0 # 給屬性指定默認值 10 11 def get_descriptive_name(self): 12 """返回整潔的描述性信息""" 13 long_name = str(self.year) + ' ' + self.make + ' ' + self.model 14 return long_name.title() 15 16 def read_odometer(self): 17 """打印一條指出汽車里程的消息""" 18 print("This car has " + str(self.odometer_reading) + " miles on it.") 19 20 my_new_car = Car('audi', 'a4', 2016) 21 print(my_new_car.get_descriptive_name()) 22 my_new_car.read_odometer()
運行結果
2016 Audi A4
This car has 0 miles on it.
Process finished with exit code 0
修改屬性的值
1、直接修改屬性的值
1 class Car(): 2 """一次模擬汽車的簡單嘗試""" 3 4 def __init__(self, make, model, year): 5 """初始化描述汽車的屬性""" 6 self.make = make 7 self.model = model 8 self.year = year 9 self.odometer_reading = 0 # 給屬性指定默認值 10 11 def get_descriptive_name(self): 12 """返回整潔的描述性信息""" 13 long_name = str(self.year) + ' ' + self.make + ' ' + self.model 14 return long_name.title() 15 16 def read_odometer(self): 17 """打印一條指出汽車里程的消息""" 18 print("This car has " + str(self.odometer_reading) + " miles on it.") 19 20 my_new_car = Car('audi', 'a4', 2016) 21 print(my_new_car.get_descriptive_name()) 22 my_new_car.odometer_reading = 23 # 直接修改屬性的值 23 my_new_car.read_odometer()
運行結果
2016 Audi A4 This car has 23 miles on it. Process finished with exit code 0
2、通過方法修改屬性的值
1 class Car(): 2 """一次模擬汽車的簡單嘗試""" 3 4 def __init__(self, make, model, year): 5 """初始化描述汽車的屬性""" 6 self.make = make 7 self.model = model 8 self.year = year 9 self.odometer_reading = 0 # 給屬性指定默認值 10 11 def get_descriptive_name(self): 12 """返回整潔的描述性信息""" 13 long_name = str(self.year) + ' ' + self.make + ' ' + self.model 14 return long_name.title() 15 16 def read_odometer(self): 17 """打印一條指出汽車里程的消息""" 18 print("This car has " + str(self.odometer_reading) + " miles on it.") 19 20 def update_odometer(self, mileage): 21 """將里程表讀數設置為指定的值""" 22 self.odometer_reading = mileage 23 24 my_new_car = Car('audi', 'a4', 2016) 25 print(my_new_car.get_descriptive_name()) 26 27 my_new_car.update_odometer(23) # 通過方法修改屬性的值 28 my_new_car.read_odometer()
3、通過方法對屬性的值進行遞增
1 class Car(): 2 """一次模擬汽車的簡單嘗試""" 3 4 def __init__(self, make, model, year): 5 """初始化描述汽車的屬性""" 6 self.make = make 7 self.model = model 8 self.year = year 9 self.odometer_reading = 0 # 給屬性指定默認值 10 11 def get_descriptive_name(self): 12 """返回整潔的描述性信息""" 13 long_name = str(self.year) + ' ' + self.make + ' ' + self.model 14 return long_name.title() 15 16 def read_odometer(self): 17 """打印一條指出汽車里程的消息""" 18 print("This car has " + str(self.odometer_reading) + " miles on it.") 19 20 def update_odometer(self, mileage): 21 """將里程表讀數設置為指定的值 22 禁止將里程表讀數往回調 23 """ 24 if mileage >= self.odometer_reading: 25 self.odometer_reading = mileage 26 else: 27 print("You can't roll back an odometer!") 28 29 def increment_odometer(self, miles): 30 """將里程表讀數增加指定的量""" 31 self.odometer_reading += miles 32 33 my_used_car = Car('subaru', 'outback', 2013) 34 print(my_used_car.get_descriptive_name()) 35 36 my_used_car.update_odometer(23500) 37 my_used_car.read_odometer() 38 39 my_used_car.update_odometer(100) 40 my_used_car.read_odometer() 41 42 my_used_car.increment_odometer(100) # 通過方法對屬性的值進行遞增 43 my_used_car.read_odometer()
運行結果
2013 Subaru Outback This car has 23500 miles on it. You can't roll back an odometer! This car has 23500 miles on it. This car has 23600 miles on it. Process finished with exit code 0
繼承
給子類定義屬性和方法
1 class Car(): 2 """一次模擬汽車的簡單嘗試""" 3 4 def __init__(self, make, model, year): 5 """初始化描述汽車的屬性""" 6 self.make = make 7 self.model = model 8 self.year = year 9 self.odometer_reading = 0 # 給屬性指定默認值 10 11 def get_descriptive_name(self): 12 """返回整潔的描述性信息""" 13 long_name = str(self.year) + ' ' + self.make + ' ' + self.model 14 return long_name.title() 15 16 def read_odometer(self): 17 """打印一條指出汽車里程的消息""" 18 print("This car has " + str(self.odometer_reading) + " miles on it.") 19 20 def update_odometer(self, mileage): 21 """將里程表讀數設置為指定的值 22 禁止將里程表讀數往回調 23 """ 24 if mileage >= self.odometer_reading: 25 self.odometer_reading = mileage 26 else: 27 print("You can't roll back an odometer!") 28 29 def increment_odometer(self, miles): 30 """將里程表讀數增加指定的量""" 31 self.odometer_reading += miles 32 33 class ElectricCar(Car): 34 """電動車的獨特之處""" 35 36 def __init__(self, make, model, year): 37 """ 38 電動汽車的獨特之處 39 初始化父類的屬性,再初始化電動汽車特有的屬性 40 """ 41 super().__init__(make, model, year) 42 self.battery_size = 70 43 44 def describe_battery(self): 45 """打印一條描述電瓶容量的消息""" 46 print("This car has a " + str(self.battery_size) + "-kWh battery.") 47 48 my_tesla = ElectricCar('tesla', 'model s', 2016) 49 print(my_tesla.get_descriptive_name()) 50 my_tesla.describe_battery()
super() 是一個特殊函數,幫助Python將父類和子類關聯起來。這行代碼讓Python調用ElectricCar的父類的方法__init__(),讓ElectricCar實例包含父類的所有屬性。父類也稱為超類(superclass),名稱super因此而得名。
運行結果
2016 Tesla Model S This car has a 70-kWh battery. Process finished with exit code 0
重寫父類的方法
對於父類的方法,只要它不符合子類模擬的實物的行為,都可對其進行重寫。為此,可在子類中定義一個這樣的方法,即它與要重寫的父類方法同名。這樣,Python將不會考慮這 個父類方法,而只關注你在子類中定義的相應方法。 假設Car 類有一個名為fill_gas_tank() 的方法,它對全電動汽車來說毫無意義,因此你可能想重寫它。下面演示了一種重寫方式:
def ElectricCar(Car): --snip-- def fill_gas_tank(): """電動汽車沒有油箱""" print("This car doesn't need a gas tank!")
現在,如果有人對電動汽車調用方法fill_gas_tank() ,Python將忽略Car 類中的方法fill_gas_tank() ,轉而運行上述代碼。使用繼承時,可讓子類保留從父類那里繼 承而來的精華,並剔除不需要的糟粕。
將實例用作屬性
使用代碼模擬實物時,你可能會發現自己給類添加的細節越來越多:屬性和方法清單以及文件都越來越長。在這種情況下,可能需要將類的一部分作為一個獨立的類提取出來。 你可以將大型類拆分成多個協同工作的小類。
1 class Car(): 2 """一次模擬汽車的簡單嘗試""" 3 4 def __init__(self, make, model, year): 5 """初始化描述汽車的屬性""" 6 self.make = make 7 self.model = model 8 self.year = year 9 self.odometer_reading = 0 # 給屬性指定默認值 10 11 def get_descriptive_name(self): 12 """返回整潔的描述性信息""" 13 long_name = str(self.year) + ' ' + self.make + ' ' + self.model 14 return long_name.title() 15 16 def read_odometer(self): 17 """打印一條指出汽車里程的消息""" 18 print("This car has " + str(self.odometer_reading) + " miles on it.") 19 20 def update_odometer(self, mileage): 21 """將里程表讀數設置為指定的值 22 禁止將里程表讀數往回調 23 """ 24 if mileage >= self.odometer_reading: 25 self.odometer_reading = mileage 26 else: 27 print("You can't roll back an odometer!") 28 29 def increment_odometer(self, miles): 30 """將里程表讀數增加指定的量""" 31 self.odometer_reading += miles 32 33 class Battery(): 34 """一次模擬電動汽車電瓶的簡單嘗試""" 35 def __init__(self, battery_size = 70): 36 """初始化電瓶的屬性""" 37 self.battery_size = battery_size 38 39 def describe_battery(self): 40 """打印一條描述電瓶容量的消息""" 41 print("This car has a " + str(self.battery_size) + "-kWh battery.") 42 43 class ElectricCar(Car): 44 """電動車的獨特之處""" 45 46 def __init__(self, make, model, year): 47 """ 48 電動汽車的獨特之處 49 初始化父類的屬性,再初始化電動汽車特有的屬性 50 """ 51 super().__init__(make, model, year) 52 self.battery = Battery() 53 54 my_tesla = ElectricCar('tesla', 'model s', 2016) 55 print(my_tesla.get_descriptive_name()) 56 my_tesla.battery.describe_battery()
下面再給Battery 類添加一個方法,它根據電瓶容量報告汽車 的續航里程:
1 class Car(): 2 """一次模擬汽車的簡單嘗試""" 3 4 def __init__(self, make, model, year): 5 """初始化描述汽車的屬性""" 6 self.make = make 7 self.model = model 8 self.year = year 9 self.odometer_reading = 0 # 給屬性指定默認值 10 11 def get_descriptive_name(self): 12 """返回整潔的描述性信息""" 13 long_name = str(self.year) + ' ' + self.make + ' ' + self.model 14 return long_name.title() 15 16 def read_odometer(self): 17 """打印一條指出汽車里程的消息""" 18 print("This car has " + str(self.odometer_reading) + " miles on it.") 19 20 def update_odometer(self, mileage): 21 """將里程表讀數設置為指定的值 22 禁止將里程表讀數往回調 23 """ 24 if mileage >= self.odometer_reading: 25 self.odometer_reading = mileage 26 else: 27 print("You can't roll back an odometer!") 28 29 def increment_odometer(self, miles): 30 """將里程表讀數增加指定的量""" 31 self.odometer_reading += miles 32 33 class Battery(): 34 """一次模擬電動汽車電瓶的簡單嘗試""" 35 def __init__(self, battery_size = 70): 36 """初始化電瓶的屬性""" 37 self.battery_size = battery_size 38 39 def describe_battery(self): 40 """打印一條描述電瓶容量的消息""" 41 print("This car has a " + str(self.battery_size) + "-kWh battery.") 42 43 def get_range(self): 44 """打印一條消息,指出電瓶的續航里程""" 45 if self.battery_size == 70: 46 range = 240 47 elif self.battery_size == 85: 48 range = 270 49 50 message = "This car can go approximately " + str(range) 51 message += " miles on a full charge." 52 print(message) 53 54 55 class ElectricCar(Car): 56 """電動車的獨特之處""" 57 58 def __init__(self, make, model, year): 59 """ 60 電動汽車的獨特之處 61 初始化父類的屬性,再初始化電動汽車特有的屬性 62 """ 63 super().__init__(make, model, year) 64 self.battery = Battery() 65 66 my_tesla = ElectricCar('tesla', 'model s', 2016) 67 print(my_tesla.get_descriptive_name()) 68 my_tesla.battery.describe_battery() 69 my_tesla.battery.get_range()
運行結果
2016 Tesla Model S This car has a 70-kWh battery. This car can go approximately 240 miles on a full charge. Process finished with exit code 0
模擬實物
模擬較復雜的物件(如電動汽車)時,需要解決一些有趣的問題。續航里程是電瓶的屬性還是汽車的屬性呢?如果我們只需描述一輛汽車,那么將方法get_range() 放 在Battery 類中也許是合適的;但如果要描述一家汽車制造商的整個產品線,也許應該將方法get_range() 移到ElectricCar 類中。在這種情況下,get_range() 依然 根據電瓶容量來確定續航里程,但報告的是一款汽車的續航里程。我們也可以這樣做:將方法get_range() 還留在Battery 類中,但向它傳遞一個參數,如car_model ;在 這種情況下,方法get_range() 將根據電瓶容量和汽車型號報告續航里程。 這讓你進入了程序員的另一個境界:解決上述問題時,你從較高的邏輯層面(而不是語法層面)考慮;你考慮的不是Python,而是如何使用代碼來表示實物。到達這種境界后,你 經常會發現,現實世界的建模方法並沒有對錯之分。有些方法的效率更高,但要找出效率最高的表示法,需要經過一定的實踐。只要代碼像你希望的那樣運行,就說明你做得很 好!即便你發現自己不得不多次嘗試使用不同的方法來重寫類,也不必氣餒;要編寫出高效、准確的代碼,都得經過這樣的過程。
