《Python程式設計:從入門到實踐》第九章:類
第九章 類
面向物件程式設計;你定義一大類物件都有的通用行為。基於類建立物件時,每個物件都自動具備這種通用行為,然後可根據需要賦予每個物件獨特的個性。
根據類來建立物件被稱為例項化。你將指定可在例項中儲存什麼資訊,定義可對這些例項執行哪些操作。你還將編寫一些類來擴充套件既有類的功能,讓相似的類能夠高效地共享程式碼。
9.1 建立和使用類
建立簡單的Dog類(表示任何小狗),建立表示小狗的物件,將建立表示特定小狗的例項。
9.1.1 建立Dog類
在Python中,首字母大寫的名稱指的是類。這個類定義中的括號是空的,因為我們要從空白建立這個類。
class Dog(): """一次模擬小狗的簡單嘗試""" def _init_(self, name, age): """初始化屬性name和age""" self.name = name self.age = age def sit(self): """模擬小狗被命令時蹲下""" print(self.name.title() + " is now sitting. ") def roll_over(self): """模擬小狗被命令時打滾""" print(self.name.title() + "rolled over! ")
類中的函式稱為方法,前面所有的跟函式有關的一切都適用於方法。
1、 -init-()方法是一個特殊的方法,在根據Dog類建立新例項的時候,python都會自動執行它。 我們將方法__init__()定義成了包含三個形參:self、name和age。在這個方法的定義中,形參self必不可少,還必須位於其他形參的前面。它是一個指向例項本身的引用。讓例項能夠訪問類中的屬性和方法。
以self為字首的變數都可供類中的所有方法使用。self.name等。
像這樣可通過例項訪問的變數稱為屬性。
2、在python2.7中建立類
在Python 2.7中建立類時,需要做細微的修改——在括號內包含單詞object:
class ClassName(object):
--snip--
9.1.2 根據類建立例項
class Dog():
--snip--
my_dog = Dog('willie', 6)
print("My dog's name is " + my_dog.name.title() + ".")
print("My dog is " + str(my_dog.age) + " years old. ")
方法__init__()建立一個表示特定小狗的示例,並使用我們提供的值來設定屬性name和age。方法__init__()並未顯式地包含return語句,但Python自動返回一個表示這條小狗的例項。並且一般大寫的名稱指的都是類,小寫的才是指根據類建立的例項。
1、 訪問屬性
my_dog.name 句點表示法。python先找到例項my_dog,然後再查詢與這個例項相關聯的屬性name,在Dog類中引用這個屬性時,
2、呼叫方法
#呼叫方法
class Dog():
--snip--
my_dog = Dog('Willie', 6)
my_dog.sit()
my_dog.roll_over()
3、建立多個例項
可以按照需求根據類建立任意數量的例項。你可按需求根據一個類建立任意數量的例項,條件是將每個例項都儲存在不同的變數中,或佔用列表或字典的不同位置。
# class Dog():
# --snip--
my_dog = Dog('Willie',6)
your_dog = Dog('lucy', 3)
print("My dog's name is " + my_dog.name.title() + ".")
print("My dog is " + str(my_dog.age) + "years old. ")
my_dog.sit()
print("\nYour dog's name is " + your_dog.name.title() + ".")
print("Your dog is " + str(your_dog.age) + "years ols. ")
your_dog.sit()
9.2 使用類和例項
你需要執行的一個重要任務是修改例項的屬性。你可以直接修改例項的屬性,也可以編寫方法以特定的方式進行修改。
9.2.1 Car類
class Car():
"""一次模擬汽車的簡單嘗試"""
def __init__(self, make, model, year):
"""初始化描述汽車的屬性"""
self.make = make
self.model = model
self.year = year
def get_descriptive_name(self):
"""返回整潔的描述性資訊"""
long_name = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name.title()
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
9.2.2 給屬性指定預設值
類中的每個屬性都必須有初始值,就算這個值是0或者空字串也行。
在方法__init__()內指定這種初始值是可行的;如果你對某個屬性這樣做了,就無需包含
為它提供初始值的形參。
9.2.3 修改屬性的值
可以以三種不同的方式修改屬性的值:直接通過例項進行修改;通過方法進行設定;通過方法進行遞增(增加特定的值)。
1、直接修改屬性的值
通過例項直接訪問它。。
# 設定預設值,,,通過例項直接訪問它修改屬性的值。。
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.odometer_reading = 23
2、通過方法修改屬性的值
編寫對屬性進行更新的方法。無需直接訪問屬性,可將值傳遞給一個方法,由它在內部進行更新。。
3、通過方法對屬性的值進行遞增
有時候需要將屬性值遞增特定的量,而不是將其設定為全新的值。
你可以輕鬆地修改這個方法,以禁止增量為負值,從而防止有人利用它來回撥里程錶。
9.3 繼承
如果你要編寫的類是另一個現成類的特殊版本,可使用**繼承。**一個類繼承另一個類時,它將自動獲得另一個類的所有屬性和方法;原有的類稱為父類,新類稱為子類。子類繼承了其父類的所有屬性和方法,同時還可以定義自己的屬性和方法。
9.3.1 子類的方法__init__()
建立子類的例項時,Python首先需要完成的任務是給父類的所有屬性賦值。
class Car():
--snip--
除了方法__init__()之外,電動汽車沒有其他特有的屬性和方法。
建立子類時,父類必須包含在當前檔案中,且位於子類前面。
super()是一個特殊函式
,幫助Python將父類和子類關聯起來。父類也稱為超類。
9.3.2 Python2.7中的繼承
函式supeer()需要兩個實參:子類名和物件self。在Python 2.7中使用繼承時,務必在定義父類時在括號內指定object。
9.3.3 給子類定義屬性和方法
讓一個類繼承另一個類後,可新增區分子類和父類所需的新屬性和方法。
使用Car類的人將獲得相應的功能,而ElectricCar類只包含處理電動汽車特有屬性和行為的程式碼。
9.3.4 重寫父類的方法
對於父類的方法,只要它不符合子類模擬的實物的行為,都可對其進行重寫。
在子類中定義一個這樣的方法,即它與要重寫的父類方法同名。
現在,如果有人對電動汽車呼叫方法fill_gas_tank(),Python將忽略Car類中的方法fill_gas_tank(),轉而執行上述程式碼。使用繼承時,可讓子類保留從父類那裡繼承而來的精華,並剔除不需要的糟粕。
9.3.5 將例項用作屬性
在這種情況下,可能需要將類的一部分作為一個獨立的類提取出來。你可以將大型類拆分成多個協同工作的小類。
self.battery = Battery(),這行程式碼讓python建立一個新的Battery例項,每次__init__()被呼叫的時候,都執行該操作,因此現在每個ElectricCar例項都包含一個自動建立的Battery例項。
9.3.6 模擬實物
9.4 匯入類
Python允許你將類儲存在模組中,然後在主程式中匯入所需的模組。
9.4.1 匯入單個類
在car1.py中定義整個類Car的屬性及方法,在my_car.py中匯入類Car。
from car1 import Car #開啟模板car1,並匯入其中的Car類
my_new_car = Car('adui', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.odometer_reading = 23
my_new_car.read_odometer()
9.4.2 在一個模板中儲存多個類
雖然同一個模組中的類之間應存在某種相關性,但可根據需要在一個模組中儲存任意數量的類。
在car1.py中定義整個類Car的屬性及方法,類ElectricCar繼承了類Car,在my_electric_car.py中匯入類ElectricCar。
from car1 import ElectricCar
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
my_tesla.battery.get_range()
9.4.3 從一個模組中匯入多個類
## 9.4.3 在一個模組中匯入多個類,可在程式檔案中匯入任意數量的類。。。
from car1 import Car,ElectricCar
my_beetle = Car('volkswagen', 'beetle', 2016)
print(my_beetle.get_descriptive_name())
my_tesla = ElectricCar('tesla', 'roadster', 2016)
print(my_tesla.get_descriptive_name())
從一個模組中匯入多個類是,用逗號分隔了各個類。
9.4.4 匯入整個模組
#9.4.4 匯入整個模組
import car1
my_beetle = car1.Car('volkswagen', 'beetle', 2016)
print(my_beetle.get_descriptive_name())
my_tesla = car1.ElectricCar('tesla', 'roadster', 2016)
print(my_tesla.get_descriptive_name())
我們匯入了整個car模組,使用語法module_name.class_name訪問需要的類。
9.4.5 匯入模組中的所有類
from module_name import ,但是不推薦。
需要從一個模組中匯入很多類時,最好匯入整個模組,並使用module_name.class_name語法來訪問類。
9.4.6 在一個模組中匯入另一個模組
9.4.7 自定義工作流程
開始應讓程式碼結構儘可能簡單。先儘可能在一個檔案中完成所有的工作,確定一切都能正確執行後,再將類移到獨立的模組中。