類
面向?qū)ο缶幊淌亲钣行У能浖帉懛椒ㄖ?/p>
在面向?qū)ο缶幊讨校帉懕硎粳F(xiàn)實(shí)世界中的事物和情景的類,并基于這些類來創(chuàng)建對(duì)象,根據(jù)類來創(chuàng)建對(duì)象被稱為實(shí)例化,這讓你能夠使用類的實(shí)例;
理解面向?qū)ο缶幊逃兄谙癯绦騿T一樣看世界,還可以幫助自己明白編寫的代碼,使你與其他程序員合作更輕松。
1.1、創(chuàng)建和使用類
使用類幾乎可以模擬任何東西,類名必須大寫,一個(gè)類由方法和屬性組成,類中的函數(shù)稱為方法,可以通過實(shí)例訪問的變量稱為屬性
1.1.1、創(chuàng)建類
下面將創(chuàng)建一個(gè)dog 類,這個(gè)dog 類不是指特定的狗,而是任何的狗,對(duì)于大多數(shù)狗來說,它們都有名字和年齡,可能還會(huì)蹲下和打滾,列子如下:
# 根據(jù)dog 類創(chuàng)建的每個(gè)實(shí)例都將存儲(chǔ)名字、年齡,我們還賦予了每條狗蹲下和打滾的能力
class Dog(): # 類名必須大寫
"""一只小狗的簡單嘗試"""
def __init__(self, name, age): # 一個(gè)特殊的方法
"""初始化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() + ' roll over!')
上面列子中,init()方法,是一種特殊方法,包含了三個(gè)形參,self、name和age,self必不可少,而且必須在氣體形參之前,python調(diào)用這個(gè)方法時(shí),將自動(dòng)傳入實(shí)參self,每個(gè)與類關(guān)聯(lián)的方法調(diào)用都自動(dòng)傳遞實(shí)參self,它是一個(gè)指向?qū)嵗旧淼囊茫寣?shí)例能訪問類中的屬性和方法,調(diào)用Dog類的init方法時(shí),通過實(shí)參向Dog()傳遞名字和年齡,self自動(dòng)傳遞,不需要傳遞,因此只需給name和age提供值。
由一個(gè)類可以生成無數(shù)個(gè)對(duì)象,當(dāng)一個(gè)對(duì)象的方法被調(diào)用的時(shí)候,對(duì)象會(huì)將自身的引用作為第一個(gè)參數(shù)傳遞給該方法。
以self 為前綴的變量,可以供類中所有方法使用,我們可以通過類的任何實(shí)例來訪問這些變量,它們是類的屬性。
1.1.2、根據(jù)類創(chuàng)建實(shí)例
根據(jù)類可以創(chuàng)建無數(shù)個(gè)實(shí)例對(duì)象(instance object),也稱為類的實(shí)例化:
下面來創(chuàng)建一個(gè)表示特定的狗的實(shí)例對(duì)象:
class Dog():
--snip--
my_dog = Dog('willie', 6) # 類的實(shí)例化(實(shí)例對(duì)象),小寫
print("My dog's name is " + my_dog.name.title() + '.') # 訪問類的屬性name
print('My dog is ' + str(my_name.age) + ' years old.') # 訪問類的屬性age
------
My dog's name is willie.
My dog is 6 years old.
訪問類的屬性
要訪問類的屬性,可以使用句點(diǎn)表示法,如要訪問name的值,可以使用(my_dog.name)的方法。
調(diào)用類的方法
與訪問屬性一樣,調(diào)用方法也可以使用句點(diǎn)表示法,如要調(diào)用sit()方法,可以使用(my_dog.sit() )
class Dog():
--snip--
my_dog = Dog('willie', 6)
my_dog.sit()
my_dog.roll_over()
-------------
willie is now sitting
willie rolled over!
創(chuàng)建多個(gè)實(shí)例
根據(jù)類可以創(chuàng)建任意數(shù)量的實(shí)例,條件是將每個(gè)實(shí)例都存儲(chǔ)到不同變量中,或占用列表或字典的不同位置,下面來創(chuàng)建一個(gè)名為your_dog 的實(shí)例:
class Dog():
--snip--
my_dog = Dog('willie', 6)
your_dog = Dog('lucy', 3)
your_dog.sit()
---------------
lucy is now sitting.
1.2、使用類和實(shí)例
類創(chuàng)建后,大部分時(shí)間都是根據(jù)類創(chuàng)建實(shí)例,需要執(zhí)行的一個(gè)重要的任務(wù)是修改實(shí)例的屬性,修改屬性的值可以直接修改或者以特定方式修改:
1.2.1、給屬性指定默認(rèn)值
類中屬性都必須有初始值,哪怕是0或空字符串,在有些情況下,如設(shè)置默認(rèn)值時(shí),在方法init () 內(nèi)指定的這種初始值是可行的,如果你對(duì)某個(gè)屬性這樣做了,就無需包含為它提供初始值的形參。
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.modle
return long_name.title()
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
------
2016 Audi A4
接下來添加一個(gè)名為odometer_reading (里程讀取)的屬性,其初始值為0。還添加了一個(gè)read_odometer() 的方法,用于讀取汽車的里程表:
class Car():
def __init__(self, make, model, year):
"""初始化描述汽車的屬性"""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0 # 添加一個(gè)能存儲(chǔ)汽車?yán)锍绦畔⒌膶傩裕鋵傩阅J(rèn)值為0
def get_descriptive_name(self):
"""返回整車的描述信息"""
long_name = str(self.year) + ' ' + self.make + ' ' + self.modle
return long_name.title()
def read_odometer(self): # 增加一個(gè)讀取方法用于讀取打印汽車?yán)锍绦畔? """打印一條信息指出汽車?yán)锍?""
print('This car has ' + str(self.odometer_reading) + ' miles on it.')
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.read_odometer() # 調(diào)用read_odometer() 方法,調(diào)用self.odometer_reading 屬性的值
------
2016 Audi A4
This car has 0 miles on it.
1.2.2、修改屬性的值
修改屬性的值,有如下三種方法:
- 直接通過實(shí)例進(jìn)行修改
- 通過方法進(jìn)行設(shè)置
- 通過方法進(jìn)行遞增(增加特定值)
直接修改
將里程數(shù)(odometer_reading)修改為23,直接通過實(shí)例調(diào)用屬性,修改其值:
class Car():
--snip--
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.odometer_reading = 23 # 通過實(shí)例調(diào)用屬性,訪問并修改其值
my_new_car.read_odometer() # 調(diào)用方法打印里程信息
------
2016 Audi A4
This car has 23 miles on it.
通過方法修改屬性的值
如果有替你更新屬性的方法,就無需直接訪問屬性,而是將值傳遞給一個(gè)方法,由它在內(nèi)部進(jìn)行更新。
下面添加一個(gè)名為update_odometer() 的方法,其中有一個(gè)形參,用于接收里程數(shù):
class Car():
--snip--
def update_odometer(self, mileage): # 定義一個(gè)方法,用于內(nèi)部更新屬性odometer_reading 的值,其中一個(gè)形參用于接收里程數(shù),并將其指定為屬性odometer_reading
"""將里程數(shù)讀數(shù)設(shè)置為指定值"""
"""禁止里程往回?fù)?""
if mileage >= odometer_reading: # 修改屬性前,檢查指定的數(shù)是否合理
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.update_odometer(32) # 調(diào)用方法,并傳遞值32給形參mileage
my_new_car.read_odometer()
------------
2016 Audi A4
This car has 32 miles on it.
通過方法對(duì)屬性的值進(jìn)行遞增
有時(shí)需要將屬性值遞增特定的值,而不是設(shè)置為全新的值,比如買了一輛二手車,從購買到登記期間增加了100英里的里程:
class Car():
--snip--
def update_odometer(self, mileage):
--snip--
def increment_odometer(self, miles): # 新增方法,接受一個(gè)單位為英里的數(shù)字,并將其存儲(chǔ)到屬性self.odometer_reading中
"""將里程表讀數(shù)增加特定的量"""
self.odometer_reading += miles
my_used_car = Car('subaru', 'outback', 2013)
print(my_used_car.get_rescriptive_name())
my_used_car.update_odometer(23500)
my_used_car.read_odometer()
my_used_car.increment_odometer(100)
my_used_car.read_odometer()
------
2013 Subaru Outback
This car has 23500 miles on it.
This car has 23600 miles on it.
練習(xí)
添加一個(gè)屬性number_served,默認(rèn)值為0,創(chuàng)建一個(gè)名為restaurant 的實(shí)例,打印這家餐館有多少人在這家餐館就餐,然后修改這個(gè)值并打印它,添加一個(gè)名為set_number_served() 的方法,它能設(shè)置就餐人數(shù),調(diào)用它傳遞一個(gè)值,再打印這個(gè)值,添加一個(gè)名為increment_number_served() 的方法,它讓你能夠?qū)⒕筒腿藬?shù)遞增,調(diào)用它并傳遞一個(gè)這樣的值:你認(rèn)為這家餐館每天可能接待的就餐人數(shù):
class Restaurant():
"""創(chuàng)建一個(gè)Restaurant的類,里面包含餐廳名字,菜品類型"""
def __init__(self, restaurant_name, cuisine_type):
self.restaurant_name = restaurant_name.title()
self.cuisine_type = cuisine_type
self.number_served = 0
def describe(self):
"""顯示餐館的基本信息"""
msg = self.restaurant_name + ' serves wonderful ' + self.cuisine_type + '.'
print(msg)
def open_restaurant(self):
"""顯示餐館正在營業(yè)"""
msg = self.restaurant_name + ' is open. Come on in!'
print(msg + '\n')
def set_number_served(self, number_served):
"""顯示就餐人數(shù)"""
self.number_served = number_served
def increment_nums(self, additional_served):
"""人數(shù)遞增"""
self.number_served += additional_served
restaurant = Restaurant("alice's home", 'pizza')
restaurant.describe()
restaurant.open_restaurant()
restaurant.set_number_served(16)
print('The current number of repast is ' + str(restaurant.number_served))
restaurant.increment_nums(10)
print('The current number of repast is ' + str(restaurant.number_served))
------------------
Alice'S Home serves wonderful pizza.
Alice'S Home is open. Come on in!
The current number of repast is 16
The current number of repast is 26
1.3、繼承
編寫類時(shí),不是都是從空白開始,有時(shí)要編寫的類是另一個(gè)現(xiàn)成的類的特殊版本,可使用繼承。一個(gè)類繼承另一個(gè)類時(shí),它將自動(dòng)獲得另一個(gè)類的所有屬性和方法,被繼承的類稱為基類或父類,繼承的類稱為子類,子類也可以定義自己的屬性和方法。
下面我們來創(chuàng)建一個(gè)名為 ElectricCar()的子類,繼承于父類Car(),用來描述電動(dòng)汽車的相關(guān)信息,它具備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_time = str(self.year) + ' ' + self.make + ' ' + self.model
return long_time.title()
def read_odometer(self):
print('This car has ' + str(self.odometer_reading) + ' miles on it.')
def update_odometer(self, mileage):
"""將里程表讀數(shù)設(shè)置為指定的數(shù)"""
self.odometer_reading = mileage
def increment_odometer(self, miles):
self.odometer_reading += miles
class ElectricCar(Car): # 子類,定義子類時(shí),括號(hào)內(nèi)必須指定父類名稱
"""電動(dòng)車的獨(dú)特之處"""
def __init__(self, make, model, year): # 方法__init__()接受創(chuàng)建父類實(shí)例所需信息
"""初始化父類的屬性"""
super().__init__(make, model, year) # super()是一個(gè)特殊函數(shù),可以將父類與子類關(guān)聯(lián)起來,它可以讓python調(diào)用父類的方法__init__(),讓子類實(shí)例包含父類的所有屬性,父類也稱為超類(superclass)
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
------------------------
2016 Tesla Model S
上面例子,我們首先定一個(gè)名為ElectricCar的子類,它繼承父類Car,創(chuàng)建子類時(shí),父類必須在子類之前,定義子類時(shí)括號(hào)內(nèi)必須指定父類名稱,方法init() 接受Car實(shí)例所需的信息(初始化父類的所有屬性和方法)。
super()函數(shù)是一個(gè)特殊函數(shù),幫助python將父類與子類關(guān)聯(lián)起來,自動(dòng)找到父類的方法,不需要給出父類的名字,這行代碼讓python調(diào)用父類的方法init(),讓子類實(shí)例包含父類的所有屬性。
為子類創(chuàng)建一個(gè)實(shí)例對(duì)象my_tesla,傳入實(shí)參,它將調(diào)用子類的init() 方法,子類的init() 方法將調(diào)用父類的init() 方法。
1.3.1、給子類定義屬性和方法
繼承后,可以添加區(qū)分子類和父類所需的新屬性和方法,需要注意的是,子類可以添加任意數(shù)量的屬性和方法,但只適用子類,如果要適用子類和父類,那么應(yīng)該添加到父類中。
下面為子類ElectricCar 添加一個(gè)電動(dòng)汽車特有的屬性(電瓶),以及一個(gè)描述該屬性的方法,存儲(chǔ)電瓶的容量,并編寫一個(gè)打印電瓶描述的方法:
class Car():
--snip--
class ElectricCar(Car):
""""""
def __init__(self, make, model, year):
""""""
super().__init__(make, model, year)
self.battery_size = 70 # 添加新屬性存儲(chǔ)電瓶容量,初始值為70
def describe_battery(self): # 定一個(gè)方法,用于描述打印這輛車的電瓶容量信息
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() # 調(diào)用方法describe_battery()
------------------------
Tesla Model S 2016
This car has a 70-kwh battery.
1.3.2、重寫父類的方法
如果父類的方法不能滿足子類的需求,可以對(duì)其進(jìn)行重寫,為此可以在子類中定一個(gè)方法,與要重寫的父類方法同名,這樣python 就不會(huì)考慮這個(gè)父類的方法,而只關(guān)注這個(gè)子類中定義的相應(yīng)方法。
假設(shè)Car類有一個(gè)名為fill_gas_tank()的方法,它對(duì)電動(dòng)汽車來說沒有意義,因此你可能需要重寫它:
class Car():
--snip--
def fill_gas_tank(self):
print('This car has a gas tank.')
class ElectricCar(Car):
--snip--
def fill_gas_tank(self): # 重寫父類方法fill_gas_tank(),因?yàn)楦割惖姆椒ú荒軡M足子類
"""電動(dòng)車沒有油箱"""
print("This car doesn't need a gas tank!")
my_tesla = ElectricCar('tesla', 'model s' 2016)
my_new_car = Car('audi', 'a4', 2016)
my_tesla.fill_gas_tank() # 父類的方法一旦被重寫,父類的實(shí)例調(diào)用被重寫的方法也會(huì)被忽略
my_new_car.fill_gas_tank()
------------------
This car doesn't need a gas tank!
This car doesn't need a gas tank!
1.3.3、將實(shí)例用作屬性
使用代碼模擬實(shí)物時(shí),你可能會(huì)給類添加越來越多的細(xì)節(jié),屬性和方法以及文件越來越長,這種情況下可能需要將類的一部分作為一個(gè)獨(dú)立的類提取出來,拆分成多個(gè)協(xié)同工作的小類。
給ElectricCar 類添加細(xì)節(jié),可能會(huì)包含很多專門對(duì)汽車電瓶的屬性和方法,可以將這些屬性和方法提取出來,放到另外一個(gè)名為Battery的類中,并將Battery實(shí)例用作ElectricCar類的一個(gè)屬性:
class Car():
--snip--
class Battery(): # 定義一個(gè)新類,用于存儲(chǔ)ElectricCar的屬性和方法
"""一次模擬電動(dòng)汽車電瓶的簡單嘗試"""
def __init__(self, battery_size=70): # 設(shè)置電瓶容量初始值
"""初始化電瓶的屬性"""
self.battery_size = battery_size
def describe_battery(self):
"""打印一條描述電瓶容量的消息"""
print('This car has a ' + str(self.battery_size) + '-kwh battery.')
class ElectricCar(Car):
"""電動(dòng)車的獨(dú)特之處"""
def __init__(self, make, model, year):
"""初始化父類的屬性,再初始化電動(dòng)車的特有屬性"""
super().__init__(make, model, year)
self.battery = Battery() # 這行代碼讓python創(chuàng)建了一個(gè)新的Battery實(shí)例(由于沒有指定參數(shù),默認(rèn)值為70),并將實(shí)例存儲(chǔ)在屬性self.battert中,每當(dāng)__init__()被調(diào)用時(shí),都將執(zhí)行該操作
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery() # 調(diào)用時(shí)采用ElectricCar的實(shí)例加Battery實(shí)例的方式調(diào)用Battery中的方法
-------------------
2016 Tesla Model S
This car has a 70-kwh battery.
把子類拆分成很多小類去協(xié)同處理,看似多了很多步驟,但是可以避免子類混亂不堪,現(xiàn)在我們可以去拓展電動(dòng)汽車的其他信息,比如描述電瓶容量的續(xù)航里程,在Battery中添加一個(gè)名為get_range ()的方法,用于描述續(xù)航里程:
class Car():
--snip--
class Battery():
--snip--
def get_range(self): # 定義一個(gè)方法,用于描述打印電瓶續(xù)航里程信息
if self.battery_size == 70:
range = 240
elif self.battery_size == 85:
range = 270
msg = 'This car can go approximately ' + str(range)
msg += ' miles on a full charge.'
print(msg)
class ElectricCar(Car):
--snip--
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
my_tesla.battery.get_range() # 調(diào)用get_battery() 方法
----------------
2016 Tesla Model S
This car has a 70-kwh battery.
This car can go approximately 240 miles on a full charge.
1.4、導(dǎo)入類
隨著我們給類不斷添加功能,代碼、文件越來越長,為遵循python的總體理念,應(yīng)讓文件盡可能簡潔,為此我們可以將類存儲(chǔ)到模塊中,然后在主程序中導(dǎo)入所需的模塊即可。
1.4.1、導(dǎo)入單個(gè)類
上面我們舉例寫了一個(gè)Car類,現(xiàn)在我們把它放到一個(gè)名為car.py的文件中(模塊),再新建一個(gè)my_car.py 的文件,我們?cè)趍y_car.py 中導(dǎo)入Car 類試試:
# car.py
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):
"""將里程表讀數(shù)設(shè)置為指定的值"""
"""拒絕將里程表回?fù)?""
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print('You can not roll back an odometer!')
def increment_odometer(self, miles):
"""將里程表讀數(shù)增加指定量"""
self.odometer_reading += miles
class Battery():
"""一次模擬電動(dòng)汽車電瓶的簡單嘗試"""
def __init__(self, battery_size=70):
"""初始化電瓶的屬性"""
self.battery_size = battery_size
def describe_battery(self):
"""打印一條描述電瓶容量的信息"""
print('This car has a ' + str(self.battery_size) + '-kwh battery.')
def get_range(self):
"""打印一條消息,指出電瓶的續(xù)航里程"""
if self.battery_size == 70:
range_0 = 240
elif self.battery_size == 85:
range_0 = 270
msg = 'This car can go approximately ' + str(range_0)
msg += ' miles on a full charge.'
print(msg)
class ElectricCar(Car):
"""電動(dòng)車的獨(dú)特之處"""
def __init__(self, make, model, year):
"""初始化父類的屬性,再初始化子類的屬性"""
super().__init__(make, model, year)
self.battery = Battery()
# my_car.py
from car import Car # 從模塊car.py中導(dǎo)入Car 類
my_new_car = Car('audi', 'a4', 2016) # Car 類實(shí)例化,傳入?yún)?shù)
print(my_new_car.get_descriptive_name())
my_new_car.odometer_reading = 23
my_new_car.read_odometer()
--------------------
2016 Audi A4
This car has 23 miles on it.
1.4.2、從一個(gè)模塊中導(dǎo)入多個(gè)類
一個(gè)模塊可以存儲(chǔ)多個(gè)類,我們可以一次導(dǎo)入一個(gè)或者多個(gè)類到主程序中,
導(dǎo)入多個(gè)類時(shí),類之間用逗號(hào)分隔即可,導(dǎo)入后即可根據(jù)類創(chuàng)建任意數(shù)量的實(shí)例。
如果我們要在同一個(gè)程序中創(chuàng)建普通汽車和電動(dòng)汽車,就需要將Car 和 ElectricCar 類都導(dǎo)入:
# my_car.py
from car import Car, ElectricCar # 從模塊car.py中導(dǎo)入Car和ElectricCar 類
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.odometer_reading = 23
my_new_car.read_odometer()
my_tesla = ElectricCar('tesla', 'model s', 2016)
my_tesla.battery.describe_battery()
my_tesla.battery.get_range()
1.4.3、導(dǎo)入整個(gè)模塊
也可以導(dǎo)入整個(gè)模塊,再使用句點(diǎn)表示法訪問所需要的類,這種方法,代碼易讀,也不會(huì)與當(dāng)前文件使用的任何名稱發(fā)生沖突:
# my_car.py
import car
my_new_car = car.Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
------------------
2016 Audi A4
1.4.4、導(dǎo)入模塊中所有類
# 語法
from module_name import *
不推薦使用這種方法導(dǎo)入模塊中所有類,這樣容易導(dǎo)致名稱方面的困惑,引發(fā)難以診斷的錯(cuò)誤,應(yīng)使用導(dǎo)入模塊名,再采用句點(diǎn)表示法的方法訪問。
1.4.5、在一個(gè)模塊中導(dǎo)入另一個(gè)模塊
有時(shí)需要將類分散到多個(gè)模塊中,以免模塊太大,或在同一模塊中存儲(chǔ)不相關(guān)的類,將類存儲(chǔ)到多個(gè)模塊中時(shí),你可能會(huì)發(fā)現(xiàn)一個(gè)模塊中的類依賴與另一個(gè)模塊中的類,這種情況下,可在前一個(gè)模塊中導(dǎo)入必要的類。
下面,我們將Car 類存儲(chǔ)到模塊car.py 中,將Battery和 ElectricCar 類存儲(chǔ)到模塊 electric_car.py 中,在調(diào)用ElectricCar 類時(shí)需要依賴Car 類,因此我們可以在electric_car.py 中導(dǎo)入car.py。
# electric_car.py
"""一組可用于表示電動(dòng)汽車的類"""
from car import Car # ElectricCar需要訪問其父類,因此我們直接將Car類導(dǎo)入到該模塊中
class Battery():
--snip--
class ElectricCar():
--snip--
# my_car.py # 在my_car模塊中導(dǎo)入car和electric_car 模塊
from car import Car
from electric_car import ElectricCar
1.5、Python標(biāo)準(zhǔn)庫
Python標(biāo)準(zhǔn)庫是一組模塊,安裝的python都包含它,現(xiàn)在對(duì)類有一定的了解,可以使用其他程序員編寫好的模塊,以及標(biāo)準(zhǔn)庫中的任何函數(shù)和類,為此只需一句在程序中包含一條簡單的imp 語句,下面來看模塊collections中的一個(gè)類-----OrdereDict
OrdereDict 實(shí)例行為與字典幾乎一致,區(qū)別在于它記錄了添加鍵-值對(duì)的添加順序,而字典不能。
# favorite_language.py
from collections import OrderedDict
favorite_languages = OrderedDict()
favorite_languages['jen'] = 'Python'
favorite_languages['sarah'] = 'c'
favorite_languages['edward'] = 'ruby'
favorite_languages['phil'] = 'java'
for name, languages in favorite_languages.items():
print(name.title() + "'s favorite language is " + languages.title() + '.')
----------------------------
Jen's favorite language is Python.
Sarah's favorite language is C.
Edward's favorite language is Ruby.
Phil's favorite language is Java.
1.6、類編碼風(fēng)格
與類有關(guān)的編碼風(fēng)格問題,在編寫復(fù)雜程序更應(yīng)遵循:
- 類名:駝峰式命名法(如ElectricCar),即首字母大寫,而不是用下劃線
- 實(shí)例名:小寫格式,單詞間使用下劃線
- 每個(gè)類都應(yīng)包含一個(gè)文檔字符串,用于描述類的功能,每個(gè)模塊也應(yīng)有。
- 空行:可用來組織代碼,但不應(yīng)濫用,類中,一個(gè)空行分隔方法,模塊中,兩個(gè)空行分隔類。
- 需要同時(shí)導(dǎo)入標(biāo)準(zhǔn)庫中的模塊和你編寫的模塊時(shí),先編寫導(dǎo)入標(biāo)準(zhǔn)庫的import 語句,再添加一個(gè)空行,然后在編寫導(dǎo)入你自己編寫的模塊的import 語句,在包含多條import 語句的程序中,這種做法讓人更容易明白程序使用的各個(gè)模塊來自何方。
練習(xí)
模塊random 包含以各種方式生成隨機(jī)數(shù)的函數(shù),其中randint()返回一個(gè)位于指定范圍內(nèi)的整數(shù),創(chuàng)建一個(gè)Die 類,包含一個(gè)名為sides 的屬性,默認(rèn)值為6,編寫一個(gè)名為 roll_die()的方法,它打印位于1和骰子面數(shù)之間的隨機(jī)數(shù),創(chuàng)建一個(gè)6 面、10面、20面的骰子,再分別擲 10 次:
from random import randint # 導(dǎo)入random 模塊以及randint 函數(shù)
class Die():
def __init__(self, sides=6):
self.sides = sides
def roll_die(self):
return randit(1, self.sides) # 返回生成1 到self.sides 間的隨機(jī)數(shù),不傳入?yún)?shù)就使用默認(rèn)值 6
d_6 = Die() # Die 類實(shí)例化,6 面骰子拋擲10次
results = [] # 將結(jié)果存儲(chǔ)到 results 列表中
for roll_num in range(10):
result = d_6.roll_die()
results.append(result)
print('10 rolls of a 6-sided die:')
print(results)
d_10 = Die(sides=10) # 10 面骰子
results = []
for roll_num in range(10):
result = d_10.roll_die()
results.append(result)
print('10 rolls of a 6-sided die:')
print(results)
d_20 = Die(sides=20) # 20 面骰子
results = []
for roll_num in range(10):
result = d_10.roll_die()
results.append(result)
print('10 rolls of a 6-sided die:')
print(results)
--------------------
10 rolls of a 6-sided die:
[4, 1, 1, 1, 5, 5, 2, 2, 3, 4]
10 rolls of a 6-sided die:
[5, 2, 2, 3, 9, 4, 2, 7, 10, 8]
10 rolls of a 6-sided die:
[1, 19, 5, 18, 19, 19, 8, 10, 8, 10]