做者 | 弗拉德
來源 | 弗拉德(公衆號:fulade_me)bash
編寫類時,並不是老是要從空白開始。若是你要編寫的類是另外一個現成類的特殊版本,可以使用 繼承。一個類繼承另外一個類時,它將自動得到另外一個類的全部屬性和方法;原有的類稱爲父類, 而新類稱爲子類。子類繼承了其父類的全部屬性和方法,同時還能夠定義本身的屬性和方法。dom
建立子類的實例時,Python首先須要完成的任務是給父類的全部屬性賦值。爲此,子類的方法__init__()
須要繼承父類的方法。
例如,下面來模擬電動汽車。電動汽車是一種特殊的汽車,所以咱們能夠在前面建立的Car類的基礎上建立新類ElectricCar
,這樣咱們就只需爲電動汽車特有的屬性和行爲編寫代碼。
下面來建立一個簡單的ElectricCar
類版本,它具有Car類的全部功能:函數
class Car(): """一次模擬汽車的簡單嘗試""" def __init__(self, make, model, year): self.make = make self.model = model self.year = year self.odometer_reading = 0 def get_descriptive_name(self): long_name = str(self.year) + ' ' + self.make + ' ' + self.model return long_name.title() def read_odometer(self): print("This car has " + str(self.odometer_reading) + " miles on it.") def update_odometer(self, mileage): if mileage >= self.odometer_reading: self.odometer_reading = mileage else: print("You can't roll back an odometer!") def increment_odometer(self, miles): self.odometer_reading += miles class ElectricCar(Car): """電動汽車的獨特之處""" def __init__(self, make, model, year): """初始化父類的屬性""" super().__init__(make, model, year) my_tesla = ElectricCar('tesla', 'model s', 2016) print(my_tesla.get_descriptive_name())
首先是Car類的代碼。建立子類時,父類必須包含在當前文件中,且位於子類前面。接着咱們定義了子類ElectricCar
。定義子類時,必須在括號內指定父類的名稱。方法__init__()
接受建立Car實例所需的信息。測試
ElectricCar
內部的super()
是一個特殊函數,幫助Python將父類和子類關聯起來。這行代碼讓Python調用ElectricCar
的父類的方法__init__()
,讓ElectricCar
實例包含父類的全部屬性。父類也稱爲超類(superclass
),名稱super所以而得名。spa
接下來咱們測試一下繼承的做用,咱們嘗試建立一輛電動汽車,但提供的信息與建立普通汽車時相同。咱們建立ElectricCar
類的一個實例,並將其存儲在變量my_tesla
中。這行代碼調用ElectricCar
類中定義的方法__init__()
,後者讓Python調用父類Car中定義的方法 __init__()
。咱們提供了實參'tesla'、'model s'和2016。
除方法__init__()
外,電動汽車沒有其餘特有的屬性和方法。當前,咱們只想確認電動汽車具有普通汽車的行爲,輸出結果以下:code
2016 Tesla Model S
ElectricCar實例的行爲與Car實例同樣,如今能夠開始定義電動汽車特有的屬性和方法了。繼承
讓一個類繼承另外一個類後,可添加區分子類和父類所需的新屬性和方法。
下面來添加一個電動汽車特有的屬性(電瓶),以及一個描述該屬性的方法。咱們將存儲電瓶容量,並編寫一個打印電瓶描述的方法:ip
class ElectricCar(Car): def __init__(self, make, model, year): """電動汽車的獨特之處 初始化父類的屬性,再初始化電動汽車特有的屬性 """ super().__init__(make, model, year) self.battery_size = 70 def describe_battery(self): """打印一條描述電瓶容量的消息""" print("This car has a " + str(self.battery_size) + "-kWh battery.") my_tesla = ElectricCar('tesla', 'model s', 2016) print(my_tesla.get_descriptive_name()) my_tesla.describe_battery()
咱們添加了新屬性self.battery_size
,並設置其初始值。根據ElectricCar
類建立的全部實例都將包含這個屬性,但全部Car實例都不包含它。咱們還添加了一個名爲describe_battery()
的方法,它打印有關電瓶的信息。咱們調用這個方法時,將看到一條電動汽車特有的描述:rem
2016 Tesla Model S This car has a 70-kWh battery.
對於ElectricCar類的特殊化程度沒有任何限制。模擬電動汽車時,你能夠根據所需的準確程度添加任意數量的屬性和方法。若是一個屬性或方法是任何汽車都有的,而不是電動汽車特有的,就應將其加入到Car類而不是ElectricCar類中。這樣,使用Car類的人將得到相應的功能,而 ElectricCar類只包含處理電動汽車特有屬性和行爲的代碼。get
對於父類的方法,只要它不符合子類模擬的實物的行爲,均可對其進行重寫。爲此,可在子類中定義一個這樣的方法,即它與要重寫的父類方法同名。這樣,Python將不會考慮這個父類方法,而只關注你在子類中定義的相應方法。
假設Car
類有一個名爲fill_gas_tank()
的方法,它對全電動汽車來講毫無心義,所以你可能想重寫它。下面演示了一種重寫方式:
def ElectricCar(Car): def fill_gas_tank(): """電動汽車沒有油箱""" print("This car doesn't need a gas tank!")
如今,若是有人對電動汽車調用方法fill_gas_tank()
,Python將忽略Car類中的方法fill_gas_tank()
,轉而運行上述代碼。使用繼承時,可以讓子類保留從父類那裏繼承的有用的代碼,用重寫來覆蓋不須要的代碼。
本篇文章沒有做業,下一篇咱們講解函數的高級用法