第二章 變量和簡單數(shù)據(jù)類型
運(yùn)行py文件時(shí)發(fā)生的情況
運(yùn)行hello_world.py文件時(shí),末尾的.py指出這是一個(gè)Python程序,因此編輯器將使用Python解釋器來運(yùn)行它。Python解釋器讀取整個(gè)程序,確定每個(gè)單詞的含義。例如print,解釋器就將括號里的內(nèi)容打印到屏幕上。
變量名只能包含字母、數(shù)字和下劃線,不能以數(shù)字開頭,而且應(yīng)該全部小寫。
字符串拼接
first_name = 'ada'
last_name = 'lovelace'
full_name = first_name + " " + full_name
使用制表符或換行符來添加空白
print("Languages:\n\tPython\n\tJavaScript")
刪除空白
favorite_language = 'python '
favorite_language.rstrip()
strip()和lstrip()是刪除開頭的空格
rstrip()是刪除結(jié)尾的空格
第三章 列表
列表簡介
bicycles = ['trek', 'cannondale', 'redline', 'specialized']
列表是有序集合,因此要訪問列表的任何元素,只需要將元素的位置或者索引告訴Python即可。
索引是從0開始
索引的最后一個(gè)是-1,倒數(shù)第二個(gè)是-2,以此類推。
修改列表元素
motocycles = ['honda', 'yamaha', 'suzuki']
mococycles[0]='ducati'
添加元素
1、在末尾添加
motocycles = [] #先創(chuàng)建空的列表
motocycles.append('ducati')
2、在列表中插入元素
motocycles = ['honda', 'yamaha', 'suzuki']
motocycles.insert(1, 'ducati')
方法insert()在索引1處添加空間,并將值'ducati'存儲(chǔ)到這個(gè)地方。這種操作將列表中排序1之后的每個(gè)元素都右移一個(gè)位置。
3、從列表中刪除元素
motocycles = ['honda', 'yamaha', 'suzuki']
del motocycles[0]
pop刪除
motocycles.pop()
彈出列表最后一個(gè)元素
彈出特定位置元素
motocycles.pop(1) #彈出第二個(gè)元素
被彈出的元素可以繼續(xù)復(fù)制使用
比如first_owned = motocycles.pop(0)
雖然列表中沒有該元素,但是該元素值可以繼續(xù)使用
4、根據(jù)值刪除元素
motocycles = ['honda', 'yamaha', 'suzuki']
motocycles.remove('honda')
組織列表
sort()對列表進(jìn)行永久排序
sort(reverse=True)倒序排序
sorted()對列表進(jìn)行臨時(shí)排序,原來的列表的順序并沒有變
reverse()反轉(zhuǎn)列表,這里的反轉(zhuǎn)是指元素的排列順序反轉(zhuǎn)
len()確定列表的長度
第四章 操作列表
遍歷列表list
motocycles = ['honda', 'yamaha', 'suzuki']
for moto in motocycles:
print(moto)
創(chuàng)建數(shù)字列表
使用函數(shù)range(),range()讓你能夠生成一系列的數(shù)字。
for value in range(1,5):
print(value)
打印不包括5
要?jiǎng)?chuàng)建數(shù)字列表,可以使用函數(shù)list()將range()的結(jié)果直接轉(zhuǎn)換為列表。
numbers = list(range(1,5))
print(numbers)
[1,2,3,4]
range()還可以指定步長,如range(2,11,2),從2開始,不斷的加2,直到11(不包括11)
數(shù)字列表的簡單計(jì)算
min(numbers)
max(numbers)
sum(numbers)
使用列表的一部分
切片
列表的部分元素-Python稱之為切片
players = ['charles', 'martina', 'michael, 'florence', 'eli']
提取第2-4個(gè)元素。
players[1:4]
如果沒有指定第一個(gè)索引,那就是從開頭開始
players[:4]
如果沒有指定第二個(gè)索引,那就直接到末尾
players[2:]
負(fù)數(shù)索引能夠讓你輸出特定位置到列表末尾的所有元素
players[-2:]
將輸出-1,-2兩個(gè)元素
遍歷切片
for player in players[1:3]:
print player
復(fù)制列表
假如我喜歡的食物,有一個(gè)朋友也喜歡,然后我喜歡的列表多了一樣,朋友喜歡的也多了一樣。
剛開始三樣一樣,如何復(fù)制列表?
my_foods =['pizza', 'falafel', 'carrot cake']
friend_foods = my_foods
my_foods.append('cannoli')
friend_foods.append('ice cream')
print(my_foods)
print(friend_foods)
你會(huì)發(fā)現(xiàn),這兩個(gè)列表輸出的一模一樣,而且cannoli和ice cream都在列表里面。為什么呢,因?yàn)閒riend_foods = my_foods并沒有復(fù)制列表,而只是新建了一個(gè)friend_foods變量,關(guān)聯(lián)到原來的my_foods上。所以,改動(dòng)其實(shí)是在一個(gè)列表上。
那如何正確復(fù)制?利用切片。
my_foods =['pizza', 'falafel', 'carrot cake']
friend_foods = my_foods[:]
my_foods.append('cannoli')
friend_foods.append('ice cream')
print(my_foods)
print(friend_foods)
元組tuple
列表可以動(dòng)態(tài)調(diào)整,使得滿足各種需求,如果你有不變的列表,那這樣的列表可以被稱為元組。
定義元組
元組看起來和列表類似,區(qū)別在于元組是圓括號,列表是方括號。
dimensions = (200, 50)
dimensions[0] = 250
這里復(fù)制會(huì)報(bào)錯(cuò),因?yàn)閠uple不能被改變
遍歷元組
for dimension in dimensions:
print(dimension)
雖然不能更改單個(gè)元組某個(gè)元素的值,但是可以更改整個(gè)元組的值。
dimensions = (200, 50)
dimensions = (400, 100)
這里并不會(huì)報(bào)錯(cuò)。
第五章 if語句
判斷相等 ==
判斷不等 !=
檢查特定值是否包含在列表中
request_topping=['mushrooms', 'onions', 'pineapple']
'mushrooms' in request_toppings
判斷特定值是否不包含在列表中
if 'mushrooms' not in request_toppings:
if else
if elif else
if
第六章 字典
字典:包含key-value鍵值對的數(shù)據(jù)結(jié)構(gòu)。
alien={'color':'green', 'points':5}
可將任何字段用作key,包括數(shù)字、字符串、列表乃至字典。
訪問字典中的值
alien['color']
添加鍵值對
alien['x_position']=0
alien['y_position']=250
空字段
alien={}
修改字典中的值
alien['color']=‘yellow'
刪除鍵值對
del alien['points']
遍歷字典
for key,value in alien:
print(key,value)
注意,鍵值對返回的順序和存儲(chǔ)順序不同,Python不關(guān)心鍵值對的存儲(chǔ)順序,而只關(guān)心鍵值對之間的關(guān)聯(lián)關(guān)系。
遍歷字典中的所有鍵
for key in alien.keys():#for key in alien效果一樣
按順序遍歷字典中所有鍵
要以特定的順序返回元素,一種方法是在for循環(huán)中對返回的鍵進(jìn)行排序,為此,可以用sorted()來排序
for key in sorted(alien.keys()):
遍歷字典中所有值
for value in alien.values():
如果值有重復(fù),那輸出重復(fù)的值沒有意義,如何去重:可以使用集合
for value in set(alien.values()):
嵌套
字典列表
alien_0={'color':'green', 'points':5}
alien_1={'color':'yellow', 'points':10}
aliens = [alien_0, alien_1]
在字典中存儲(chǔ)列表
pizza = {'crust':'thick', 'topping': ['mushroom','extra cheese'],}
在字典中存儲(chǔ)字典
用戶輸入和while循環(huán)
name = input("Please enter your name:")
print(name)
input()將用戶輸入解讀為字符串
如果輸入的是數(shù)字字符串,可以通過int()將其轉(zhuǎn)化成數(shù)字
求模運(yùn)算符
4%3
求模運(yùn)算符,將兩個(gè)數(shù)相除并符合余數(shù)。
active = True
while active:
message=input()
if message == 'quit':
active = False
else:
print(message)
另一種寫法:break
使用break退出循環(huán)
while True:
message=input()
if message == 'quit':
break
else:
print(message)
continue:繼續(xù)使用循環(huán),從頭開始執(zhí)行
打印10以內(nèi)的奇數(shù)
current_number = 0
while current_number < 10:
current_number += 1
if current_number % 2 == 0:
continue
print(current_number)
for循環(huán)是一種遍歷列表的有效方式,但在for循環(huán)中不應(yīng)該修改列表,否則將導(dǎo)致python難以跟蹤其中元素。如果要在遍歷列表的同時(shí)對其修改,可以使用while循環(huán)。
unconfirmed_users = ['alice','brain', 'candace']
while unconfirmed_users:
current_user = unconfirmed_users.pop()
刪除包含特定值的所有列表元素
pets = ['dog','cat','dog','goldfish','cat','rabbit','cat']
while 'cat' inpets:
pets.remove('cat')
函數(shù)
def greet_user(username):
print("hello!," + username.title() + "!")
greet_user('sarah')
實(shí)參和形參
username是一個(gè)形參,'sarah'是一個(gè)實(shí)參。將實(shí)參'sarah'傳遞給函數(shù)的形參username,值被存儲(chǔ)在形參username中。
位置實(shí)參
def describe_pet(animal_type, pet_name):
print("\nI have a " + animal_type +".")
print("My " + animal_type + "'s name is " + pet_name.title() + ".")
describe_pet('dog', 'willie')
調(diào)用函數(shù)時(shí),Python必須將函數(shù)調(diào)用中的每個(gè)實(shí)參都關(guān)聯(lián)到函數(shù)定義中的一個(gè)形參,最簡單的關(guān)聯(lián)方式就是基于實(shí)參的順序。這種關(guān)聯(lián)方式稱為位置實(shí)參。
關(guān)鍵字實(shí)參
關(guān)鍵字實(shí)參是傳遞給函數(shù)的名稱-值對。你直接在實(shí)參中將名稱和值關(guān)聯(lián)起來。因此向函數(shù)傳遞實(shí)參時(shí)不會(huì)混淆。關(guān)鍵字實(shí)參讓你無需考慮函數(shù)調(diào)用中的實(shí)參順序,還清楚的指出了函數(shù)調(diào)用中各值的用途。
describe_pet(animal_type = 'dog', pet_name = 'willie')
默認(rèn)值
def describe_pet(pet_name, animal_type='dog'):
print("\nI have a " + animal_type +".")
print("My " + animal_type + "'s name is " + pet_name.title() + ".")
describe_pet(pet_name='willie')
也可以通過位置實(shí)參調(diào)用
describe_pet('willie')
使用默認(rèn)值時(shí),在形參列表中必須先列出沒有默認(rèn)值的形參,再列出有默認(rèn)值的形參。這讓Python依然能夠正確解讀位置參數(shù)。
返回值
def get_formatted_name(first_name, last_name):
full_name = first_name + ' ' + last_name
return full_name.title()
返回字典
def build_person(first_name,last_name):
person = {'first_name':first_name,'last_name':last_name}
return person
禁止函數(shù)修改列表
有時(shí)候,我們需要禁止修改列表。為了解決這個(gè)問題,可以向函數(shù)傳遞列表的副本,而不是列表本身,這樣對列表的修改只是在副本上。不會(huì)影響列表本身。也就是傳遞列表的切片
function(last_name(:))
傳遞任意數(shù)量的實(shí)參
一個(gè)制作披薩的函數(shù),它需要接受很多配料,但你無法預(yù)先確定顧客要多少種配料。
def make_pizza(*toppings):
for topping in toppings:
print("- " + topping)
make_pizza('pepperoni')
make_pizza('mushrooms','green peppers','extra cheese')
形參名*toppings中的星號讓Python創(chuàng)建一個(gè)名為toppings的空元組,并將收到的所有值都封裝到這個(gè)元組中。
結(jié)合使用位置實(shí)參和任意數(shù)量實(shí)參
如果要讓函數(shù)接受不同類型的實(shí)參,必須在函數(shù)定義中將接納任意數(shù)量實(shí)參的形參放在最后。Python先匹配位置實(shí)參和關(guān)鍵字實(shí)參,再將余下的實(shí)參都收集到最后一個(gè)形參中。
def make_pizza(size, *toppings):
print("\nMaking a "+ str(size) + "-inch pizza with following toppings:")
for topping in toppings:
print("- " + topping)
make_pizza(16,'pepperoni')
基于函數(shù)定義,Python將第一個(gè)值存儲(chǔ)在形參中,并將其他所有值存儲(chǔ)在元組toppings中。
使用任意數(shù)量的關(guān)鍵字實(shí)參
def build_profile(first, last, **user_info):
profile={}
profile['first_name'] = first
profile['last_name'] = last
for key,value in user_info:
profile[key] = value
return profile
build_profile('albert', 'einstein', location='princeton', field='physics')
函數(shù)的定義要求提供名和姓,同時(shí)允許用戶根據(jù)需要提供任意數(shù)量的名稱-鍵值對,形參*user_inmfo中的兩個(gè)號讓Python創(chuàng)建一個(gè)名為user_info的空字典。并將收到的所有鍵值對都封裝到這個(gè)字典中??梢韵裨L問其他字典那樣訪問user_info鍵值對
將函數(shù)存儲(chǔ)在模塊中,可以通過import來使用模塊中的函數(shù)
導(dǎo)入整個(gè)模塊
pizza.py
def make_pizza(size, *toppings):
print("\nMaking a "+ str(size) + "-inch pizza with following toppings:")
for topping in toppings:
print("- " + topping)
我們在pizza.py目錄創(chuàng)建另一個(gè)making_pizzas.py文件,導(dǎo)入pizzs模塊,再調(diào)用make_pizza()兩次
making_pizzas.py
import pizza
pizza.make_pizza(16, 'pepperoni')
pizza.make_pizza(12, 'mushrooms','green peppers','extra cheese')
Python讀取這個(gè)文件時(shí),代碼行import pizza讓Python打開文件pizza.py,并將其中的所有的函數(shù)都復(fù)制到這個(gè)程序中。調(diào)用方法就是模塊名,后面加.,最后再加函數(shù)名
module_name.fuction_name()
導(dǎo)入特定函數(shù)
from module_name import fuction_name0, fuction_name1
通過這種方式導(dǎo)入的函數(shù),可以直接用fuction_name0()進(jìn)行調(diào)用
使用as給指定函數(shù)指定別名
如果要導(dǎo)入的函數(shù)的名稱可能與程序中的現(xiàn)有名稱沖突,或者函數(shù)名稱太長,可指定簡短且獨(dú)一無二的別名。
from module_name import function_name as fn
from pizza import make_pizza as mp
mp(16, 'pepperoni')
mp(12, 'mushrooms','green peppers','extra cheese')
使用as給模塊指定別名
import module_name as mn
import pizza as p
p.make_pizza(16, 'pepperoni')
p.make_pizza(12, 'mushrooms','green peppers','extra cheese')
導(dǎo)入模塊中所有函數(shù)
from pizza import *
make_pizza(16, 'pepperoni')
make_pizza(12, 'mushrooms','green peppers','extra cheese')
import語句中的*讓Python將模塊pizza中的每個(gè)函數(shù)都復(fù)制到這個(gè)程序文件中。由于導(dǎo)入了每個(gè)函數(shù),可通過名稱來調(diào)用每個(gè)函數(shù),而無需使用句點(diǎn)表示法。然而,使用并非自己編寫的大型模塊時(shí),最好不要采用這種導(dǎo)入方法:如果模塊中有函數(shù)的名稱與你的項(xiàng)目中使用的名稱相同,可能導(dǎo)致意想不到的結(jié)果:Python可能遇到多個(gè)名稱相同的函數(shù)活變量,進(jìn)而覆蓋函數(shù),而不是分別導(dǎo)入所有的函數(shù)。
最佳的做法是,要么只導(dǎo)入你需要用的函數(shù),要么導(dǎo)入整個(gè)模塊并使用句點(diǎn)法
函數(shù)編寫指南
1、函數(shù)名稱只用小寫字母和下劃線
2、函數(shù)都應(yīng)包含簡要闡述期功能的注釋
3、參數(shù)的意義的注釋
第九章 類
創(chuàng)建dog類
class Dog():
"""一次模擬小狗的簡單嘗試"""
def __init__(self, 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.")
方法 init()
類中的函數(shù)稱為方法,init()是一個(gè)特殊的方法,每當(dāng)你根據(jù)Dog類創(chuàng)建新實(shí)例時(shí),Python就會(huì)自動(dòng)運(yùn)行它。在這個(gè)方法的名稱中,開頭和結(jié)尾各有兩個(gè)下劃線,這是一種約定,旨在避免Python默認(rèn)方法與普通方法發(fā)生沖突。
init()包含三個(gè)形參,self、name和age。在這個(gè)方法的定義中,形參self必不可少,還必須位于其他形參的前面。因?yàn)镻ython調(diào)用init()方法創(chuàng)建Dog實(shí)例時(shí),將自動(dòng)傳入實(shí)參self。每個(gè)與類相關(guān)聯(lián)的方法調(diào)用都自動(dòng)傳遞實(shí)參self,它是指向?qū)嵗旧淼囊?,讓?shí)例能夠訪問類中的屬性和方法。我們創(chuàng)建Dog實(shí)例時(shí),Python將調(diào)用Dog類的方法,init(),我們將通過實(shí)參向Dog()傳遞名字和年齡,self會(huì)自動(dòng)傳遞。
init方法里面兩個(gè)變量都有前綴self,以self為前綴的變量都可供類中的所有方法使用,我們還可以通過類的任何實(shí)例訪問這些變量。self.name=name獲取存儲(chǔ)在形參name中的值,并將其存儲(chǔ)到變量name中,然后將該變量關(guān)聯(lián)到當(dāng)前創(chuàng)建的實(shí)例。像這樣可通過實(shí)例訪問的變量稱為屬性。
Dog類還定義了另外兩個(gè)方法:sit()和roll_over()。由于這些方法不需要額外的參數(shù),因此他們只有一個(gè)形參self。
根據(jù)類創(chuàng)建實(shí)例
my_dog = Dog('willie', 6)###調(diào)用init()創(chuàng)建特定小狗實(shí)例
print("My dog's name is " + my_dog.name.title() + ".")
print("My dog's is " + str(my_dog.age) + " years old.")
訪問屬性
要訪問實(shí)例的屬性,可使用句點(diǎn)法表示。my_dog.name
調(diào)用方法
my_dog.sit()
使用類和實(shí)例
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)
給屬性指定默認(rèn)值
class Car():
"""一次模擬汽車的簡單嘗試"""
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.odometer = 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.")
修改屬性的值
my_new_car.odometer = 23
my_new_car.read_odometer()
通過方法修改屬性的值
class Car():
"""一次模擬汽車的簡單嘗試"""
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.odometer = 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):
self.odomter = mileage
my_new_car.update_odometer(23)
通過方法對屬性的值進(jìn)行遞增
def increment_odometer(self, miles):
self.odometer += miles
my_new_car.increment_odometer(50)
class Car():
"""一次模擬汽車的簡單嘗試"""
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.odometer = 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):
self.odomter = mileage
def increment_odometer(self, miles):
self.odometer += miles
class ElectricCar(Car):
"""電動(dòng)汽車的獨(dú)特之處"""
def __init__(self, make, model, year):
super().__init__(make, model, year)
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
創(chuàng)建子類時(shí),父類必須包含在當(dāng)前文件中,且位于子類之前。
super()函數(shù)是一個(gè)特殊函數(shù),幫助Python將父類和子類關(guān)聯(lián)起來。
給子類定義屬性和方法
class Car():
"""一次模擬汽車的簡單嘗試"""
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.odometer = 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):
self.odomter = mileage
def increment_odometer(self, miles):
self.odometer += miles
class ElectricCar(Car):
"""電動(dòng)汽車的獨(dú)特之處"""
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.describe_battery()
重寫父類方法
假設(shè)Car類有一個(gè)名為fill_gas_tank()的方法,它對電動(dòng)汽車毫無意義,因此可以重寫他
class ElectricCar(Car):
--snip--
def fill_gas_tank(self):
print("This car doesn't need a gas tank!")
將實(shí)例用作屬性
可能需要將類的一部分作為一個(gè)獨(dú)立的類提取出來??梢詫⒋笮皖惒鸱殖啥鄠€(gè)協(xié)同工作的小類。
class Car():
--snip--
class Battery():
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.")
class ElectricCar(Car):
def __init__(self,make, model, year):
super().__init__(make, model, year)
self.battery = Battery()
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
導(dǎo)入類
由于類不斷的添加功能,文件變的很長,為了讓文件盡可能整潔,Python允許你將類存儲(chǔ)在模塊中,然后在主程序中導(dǎo)入所需模塊
導(dǎo)入單個(gè)類
car.py
"""一個(gè)可用于表示汽車的類"""
class Car():
"""一次模擬汽車的簡單嘗試"""
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.odometer = 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):
self.odomter = mileage
def increment_odometer(self, miles):
self.odometer += miles
my_car.py
from car import Car##從文件中導(dǎo)入類,可用利用逗號,一次引入多個(gè)類
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.odometer = 23
my_new_car.read_odometer()
導(dǎo)入整個(gè)模塊
可用import car導(dǎo)入整個(gè)模塊。接下來,我們使用module_name.class_name訪問需要的類
導(dǎo)入模塊所有類
from car import *
不推薦這種導(dǎo)入方式,其原因有二:
1、如果只要看一下文件開頭的import語句,就能清楚知道程序使用了哪些類,將大有裨益。但這種方式并沒有明確你使用了模塊中哪些類
2、這種導(dǎo)入方式還可能引發(fā)名稱方面的困惑。如果你不小心導(dǎo)入了一個(gè)與程序文件中其他同名的類,可能引發(fā)錯(cuò)誤。
在一個(gè)模塊中引入另一個(gè)模塊
這個(gè)用法和普通的模塊引入沒有任何區(qū)別,比如把Car類和ElectricCar分成兩個(gè)模塊文件,任何在ElectricCar里面from car import Car
后面如果需要導(dǎo)入Car和ElectricCar類的時(shí)候,不能以為ElectricCar類里面導(dǎo)入了Car就不需要再導(dǎo)入了。所以,Car類和ElectricCar類都需要單獨(dú)導(dǎo)入。
類編碼風(fēng)格
1、類名應(yīng)采取駝峰命名法,將類名中的每個(gè)首字母大寫,而不使用下劃線。實(shí)例名和模塊名都是小寫格式,并在單詞之間加上下劃線。
2、對于每個(gè)類,都應(yīng)緊跟在類定義后面包含一個(gè)文檔字符串。描述累的功能。每個(gè)模塊也都要包含一個(gè)文檔字符串,對其中的類的行為進(jìn)行描述
3、在類中,可使用一個(gè)空行來分隔方法;而在模塊中,可使用兩個(gè)空行來分隔類。
4、需要同時(shí)導(dǎo)入標(biāo)準(zhǔn)庫中的模塊和你自己編寫的模塊時(shí),先導(dǎo)入標(biāo)準(zhǔn)庫模塊的import語句,再添加一個(gè)空行,然后再編寫導(dǎo)入你自己編寫的模塊的import語句。這種做法讓人更容易明白程序使用的各個(gè)模塊來自何方。
總結(jié):
除了類名是駝峰命名法,首字母大寫,其他比如實(shí)例、模塊名、函數(shù)名、方法名、變量名都是小寫加下劃線,導(dǎo)入變量名還可以加數(shù)字。
第十章 文件和異常
with open('pi_digits.txt') as file_object:
contents = file_object.read()
print(contents)
這里有調(diào)用open(),但是沒有調(diào)用close()。用with打開文件,Python會(huì)自動(dòng)在合適的時(shí)候調(diào)用close()關(guān)閉文件。
這個(gè)輸出會(huì)多一行,原因在于read()到達(dá)文件末尾時(shí)返回一個(gè)空字符串,而將這個(gè)空字符串顯示出來就是一個(gè)空行。要?jiǎng)h除空行,可以在print里面使用rstrip()
print(contents.rstrip())
上面的open的文件沒有帶路徑,Python會(huì)自動(dòng)搜索程序文本所在的當(dāng)前文件夾。
文件路徑
相對路徑
linux和os x系統(tǒng)
with open('text_files/filename.txt') as file_object
windows系統(tǒng)
with open('text_files\filename.txt') as file_object
絕對路徑
linux和os x系統(tǒng)
file_path = '/home/ehmatthes/text_files/filename.txt'
with open(file_path) as file_object
windows系統(tǒng)
file_path = 'C:\Users\ethmatthes\other_files\text_files\filename.txt'
with open(file_path) as file_object
逐行讀取
filename = 'pi_digits.txt'
with open(filename) as file_object:
for line in file_object:
print(line.rstrip())
調(diào)用open后,將一個(gè)表示文件及其內(nèi)容的對象存儲(chǔ)到變量file_object中。
創(chuàng)建一個(gè)包含文件各行內(nèi)容的列表
filename = 'pi_digits.txt'
with open(filename) as file_object:
for line in file_object:
lines = file_object.readlines()
for line in lines:
print(line.strip())
lines列表中的每個(gè)元素就是file_object的每一行內(nèi)容。
filename = 'pi_millon_digits.txt'
with open(filename) as file_object:
lines = file_object.readlines()
pi_string = ''
for line in lines:
pi_string += line.strip()
print(pi_string[:52] + "...")
圓周率是否包含你的生日
filename = 'pi_millon_digits.txt'
with open(filename) as file_object:
lines = file_object.readlines()
pi_string = ''
for line in lines:
pi_string += line.strip()
birthday = input("Enter your birthday, in the form mmddyy:")
if birthday in pi_string:
print("Your birthday appears in the first millon digits of pi!")
else:
print("Your birthday does not appears in the first millon digits of pi!")
寫入文件
filename = 'programming.txt'
with open(filename,'w') as file_object:
file_object.write("I love programming.")
調(diào)用open時(shí),提供了兩個(gè)參數(shù),第一個(gè)參數(shù)是要打開的文件的名稱,第二個(gè)參數(shù)'w'告訴Python,我們要以寫入的方式打開文件。
打開文件有幾種模式
w-寫入模式
r-只讀模式
a-附加模式
r+-讀取和寫入模式
如果省略模式實(shí)參,那Python默認(rèn)以只讀打開
如果要寫入的文件不存在,函數(shù)open()自動(dòng)創(chuàng)建它。以'w'模式打開文件要小心,如果文件以及存在,Python將返回對象前清空該文件。
Python只能將字符串寫入文本文件。要將數(shù)值數(shù)據(jù)存儲(chǔ)到文本文件,必須先試用str()函數(shù)將其轉(zhuǎn)換為字符串格式。
寫入多行
file_object.write("I love programming.\n")
file_object.write("I love creating new game.\n")
如果不加換行符,則會(huì)連成一行
附加到文件
如果你想給文件添加內(nèi)容,而不是覆蓋原有的內(nèi)容,可以附加模式打開文件。你以附加模式打開文件時(shí),Python不會(huì)再返回文件對象前清空文件,而你寫入到文件的行都將添加到文件末尾。如果你指定的文件不存在,Python將為你創(chuàng)建一個(gè)空文件。
異常
filename = 'alice.txt'
try:
with open(filename) as f_obj:
contents = f_obj.read()
except FileNotFoundError:
msg = "Sorry, the file " + filename + " does not exist."
print(msg)
else:
words = contents.split()
num_words = len(words)
print("The file " + filename + " has about " + str(num_words) + " words.")
存儲(chǔ)數(shù)據(jù)
使用json.dump()和json.load()
函數(shù)json.dump()接受兩個(gè)實(shí)參,要存儲(chǔ)的數(shù)據(jù)以及可用于存儲(chǔ)數(shù)據(jù)的文件對象。
import json
filename = 'username.json'
try:
with open(filename) as f_obj:
username = json.load(f_obj)
except: FileNotFoundError:
username = input("What is your name?")
with open(filename,'w') as f_obj:
json.dump(username, f_obj)
print("We'll remeber you when you come back, " + username + "!")
else:
print("Welcome back, " + username + "!")
第十一章 測試代碼
name_function.py
def get_formatted_name(first_name, last_name):
full_name = first_name + ' ' + last_name
return full_name.title()
names.py
from name_function import get_formatted
print("Enter 'q' at any time to quit.")
while True:
first = input("\nPlease give me a first name:")
if first == 'q':
break
last = input("\nPlease give me a last name:")
if last == 'q':
break
formatted_name = get_formatted_name(first,last)
print("\tNeatly formatted name:" + formatted_name + '.')
單元測試
test_name_function.py
import unittest
from name_function import get_formatted_name
class NameTestCase(unittest.TestCase):
"""測試name_function.py"""
def test_first_last_name(self):
formatted_name = get_formatted_name('janis', 'joplin')
self.assertEqual(formatted_name, 'Janis Joplin')
unittest.main()
首先我們創(chuàng)建了一個(gè)名為NameTestCase的類,用于包含一系列針對get_formatted_name()的單元測試。你可以隨便給這個(gè)類命名,但最好讓它看起來與測試的函數(shù)相關(guān),并包含Test字樣。這個(gè)類必須繼承unittest.TestCase類,這樣Python才知道如何運(yùn)行你編寫的測試。
NameTestCase只包含一個(gè)方法,用于測試get_formatted_name()的一個(gè)方面。我們將這個(gè)方法命名為test_first_last_name()。
我們運(yùn)行test_name_function.py時(shí),所有以test_打頭的方法都將自動(dòng)運(yùn)行。
方法里,我們使用了unittest類最常用的功能之一:一個(gè)斷言方法。斷言方法用來合適得到的結(jié)果是否與期望的結(jié)果一致。
unittest斷言方法
| 方法 | 用途 |
|---|---|
| assertEqual(a,b) | 核實(shí)a==b |
| assertNotEqual(a,b) | 核實(shí)a!=b |
| assertTrue(x) | 核實(shí)x為True |
| assertFalse(x) | 核實(shí)x為False |
| assertIn(item, list) | 核實(shí)item在list中 |
| assertNotIn(item, list) | 核實(shí)item不在list中 |
測試類
survey.py
class AnonymousSurvey():
"""收集匿名調(diào)查問卷答案"""
def __init__(self, question):
self.question = question
self.responses = []
def show_question(self):
print(self.question)
def store_response(self, new_response):
self.responses.append(new_response)
def show_results(self):
print("Survey results:")
for response in self.responses:
print('- ' + response)
測試AnonymousSurvey類
test_survey.py
import unittest
from survey import AnonymousSurvey
class TestAnonymousSurvey(unittest.TestCase):
"""針對AnonymousSurvey類的測試"""
def setUp(self):
question = "What language did you first leanr to speak?"
self.my_survey = AnonymousSurvey(question)
self.responses = ['English', 'Spanish', 'Mandarin']
def test_store_single_response(self):
self.my_survey.store_response(self.responses[0])
self.assertIn(self.responses[0], self.my_survey.responses)
def test_store_three_response(self):
for response in self.responses:
self.my_survey.store_response(response)
for response in self.responses:
self.assertIn(response, self.my_survey.responses)
unittest.main()
方法setUp()
在前面的測試代碼中,我們在測試方法中都單獨(dú)創(chuàng)建了AnonymousSurvey的實(shí)例。
有沒有辦法進(jìn)行優(yōu)化?
可以使用setUp(),讓我們只需創(chuàng)建這些對象一次,并在每個(gè)測試方法中運(yùn)用它們。
如果你在TestCase類中包含方法setUp(),Python將先運(yùn)行它,再運(yùn)行各個(gè)以test_打頭的方法。
import unittest
from survery import AnonymousSurvey
class TestAnonymousSurvey(unittest.TestCase):
"""針對AnonymousSurvey類的測試"""
def setUp(self):
question = "What language did you first leanr to speak?"
self.survey = AnonymousSurvey(question)
self.responses = ['English', 'Spanish', 'Mandarin']
def test_store_single_response(self):
my_survey.store_response(self.responses[0])
self.assertIn(self.responses[0], my_survey.response)
def test_store_three_response(self):
for response in responses:
my_survey.store_response(response)
for response in responses:
self.assertIn(response, my_survey.responses)
unittest.main()