python learning
-看《Python 程式設計:從入門到實踐》做的筆記
-後續整理
1搭建環境
安裝過程中,記得勾選Add Python to PATH
2變數和簡單資料型別
2.1變數
變數的命名和C語言的規則一樣,變數不用像C語言一樣指明變數型別
message = "Hello Python Crash Course reader!"
2.2字串
2.2.1修改字串大小寫
1.使首字母大寫title()
2.使全部轉為大寫或者小寫upper(),lower()
name = "ada lovelace" print(name.title()) name = "Ada Lovelace" print(name.upper()) print(name.lower())
2.2.2拼接字串
使用 +
first_name = "ada"
last_name = "lovelace"
full_name = first_name + " " + last_name
print("Hello, " + full_name.title() + "!")
2.2.3新增和刪除空白
1.新增:使用製表符\t或換行符\n或空格
2.刪除:使用 strip() 刪除兩邊的,rstrip() 刪除右邊的,lstrip() 刪除左邊的
favorite_language = ' python ' print(favorite_language.rstrip()) print(favorite_language.lstrip()) print(favorite_language.strip())
2.3數字
1.整數:加(+ ) 減(- ) 乘(* ) 除(/ ) 乘方(** )餘數(% )
2.浮點數
3.數字型轉字元型str()
2.4註釋
使用 #
3列表
類似陣列,使用方括號 [] 表示列表
bicycles = ['trek', 'cannondale', 'redline', 'specialized']
print(bicycles)
3.1使用列表
1.訪問:與C語言類似
2.修改:與C語言類似
3.新增:使用 append() ,在列表末尾新增元素
4.插入:使用 insert() ,在指定位置插入元素
5.刪除:
1)使用 del語句 ,刪除指定位置的元素
2)使用 pop()
3)使用 pop() ,刪除指定位置的元素,括號中是指定的位置
4)使用 remove() ,根據值刪除元素
bicycles = ['trek', 'cannondale', 'redline', 'specialized']
print(bicycles[0])#訪問
bicycles[0] = 'ducati'#修改
print(bicycles)
bicycles.append('ducati')#新增
print(bicycles)
bicycles.insert(0, 'yamaha')#插入
print(bicycles)
del bicycles[0]#刪除del
print(bicycles)
popped_bicycle = bicycles.pop()#刪除pop()
print(bicycles)
print(popped_bicycle)
first_owned = bicycles.pop(0)#刪除pop(n)
print(bicycles)
print(first_owned)
bicycles.remove('redline')#刪除remove()
print(bicycles)
3.2組織列表
1.永久性排序:
1)使用sort() ,按照字母順序排列
2)使用sort(reverse=True) ,按照字母相反順序排列
3)使用reverse() ,按照原來的相反順序排列,而不是隻字母順序
2.臨時性排序:使用sorted() ,不改變原來的排列順序
3.確定長度:使用len() ,
cars = ['bmw', 'audi', 'toyota', 'subaru']
cars.reverse()#永久性排序,reverse()
print(cars)
cars.sort()#永久性排序,sort()
print(cars)
cars.sort(reverse=True)#永久性排序,sort(reverse=True)
print(cars)
print(sorted(cars))#臨時性排序
print(cars)
print(len(cars))#確定長度,len()
4操作列表
4.1遍歷整個列表
使用for迴圈 需要值得注意的地方: 1)縮排代表歸屬 2)冒號
magicians = ['alice', 'david', 'carolina']
for magician in magicians:
print(magician)
4.2數值列表
1)使用range() 生成一系列數字
2)使用range() 建立數字列表
3)最大值max() ,最小值min() ,總和sum()
4)列表解析
PS :range(a,b,c)
a是頭,b是尾,c是間距
和str[a: b :c]是一樣的道理
for value in range(1,5):#1
print(value)
numbers = list(range(1,6))#2
print(numbers)
even_numbers = list(range(2,11,2))#2
print(even_numbers)
print(max(numbers))#3
print(min(numbers))#3
print(sum(numbers))#3
squares = []
for value in range(1,11):
squares.append(value**2)
print(squares)
squares = [value**2 for value in range(1,11)]##4效果和上面這段程式碼一樣
print(squares)
4.3使用列表的一部分
4.3.1切片
處理列表中的部分元素。
切片的應用場景:例如,編寫遊戲時,你可以在玩家退出遊戲時將其最終得分加入到一個列表中。然後,為獲取該玩家的三個最高得分,你可以將該列表按降序排列,再建立一個只包含前三個得分的切片。處理資料時,可使用切片來進行批量處理;編寫Web應用程式時,可使用切片來分頁顯示資訊,並在每頁顯示數量合適的資訊。
1)要指定使用的第一個元素和最後一個元素的索引
2)如果未指定第一個元素,預設為列表開頭
3)如果未指定最後一個元素,預設為列表末尾
4)還可以指定負數。離列表末尾相應距離的元素
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players[0:3])#1
print(players[1:4])#1
print(players[:4])#2
print(players[2:])#3
print(players[-3:])#4
4.3.2遍歷切片
for迴圈使用切片
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print("Here are the first three players on my team:")
for player in players[:3]:
print(player.title())
4.3.3複製列表
要複製列表,可建立一個包含整個列表的切片,方法是同時省略起始索 引和終止索引([:]) 。這讓Python建立一個始於第一個元素,終止於 最後一個元素的切片,即複製整個列表。如果沒有使用([:]),就會出現如下情況,複製指標
my_foods = ['pizza', 'falafel', 'carrot cake']
friend_foods = my_foods[:]
print(my_foods)
print(friend_foods)
?#錯誤例項
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)
4.4元組
列表是可以修改的,不可修改的列表叫做元組,使用圓括號來標識
dimensions = (200, 50)
print(dimensions[0])
print(dimensions[1])
dimensions[0] = 250#這條程式碼無法執行,禁止修改
4.4.1遍歷元組中所有值
和列表一樣
dimensions = (200, 50)
for dimension in dimensions:
print(dimension)
4.4.2修改元組變數
雖然不能修改元組的元素,但是可以儲存元組的變數賦值。即重新定義整個元組
dimensions = (400, 100)
for dimension in dimensions:
print(dimension)
dimensions = (200, 50)
for dimension in dimensions:
print(dimension)
4.5設定程式碼格式
1.PEP 8建議每級縮排都使用四個空格
2.很多Python程式設計師都建議每行不超過79字元
3.PEP 8還建議註釋的行長都不超過72字元
4.要將程式的不同部分分開,可使用空行
5 if語句
使用方法與C語言大同小異
5.1條件測試
1.檢測是否相等 if car == ‘audi’
2.檢查是否相等時不考慮大小寫 if car.lower() == ‘audi’
3.檢查是否不相等 if requested_topping != ‘anchovies’
4.比較數字 if answer <= 42
5.檢查多個條件 and 和 or
6.檢查特定值是否包含在列表中 if ‘pepperoni’ in requested_toppings
7.檢查特定值是否不包含在列表中 if user not in banned_users:
8.布林表示式
5.2if語句
1.if
2.if-else
3.if-elif-else
4.多個elif
5.省略else
6.多個if(並非巢狀)
5.3if語句處理列表
5.3.1檢查特殊元素
即在for迴圈中巢狀if語句
requested_toppings = ['mushrooms', 'green peppers', 'extra cheese']
for requested_topping in requested_toppings:
if requested_topping == 'green peppers':
print("Sorry, we are out of green peppers right now.")
else:
print("Adding " + requested_topping + ".")
5.4.2確定列表不是空的¶
In [ ]:
requested_toppings = []
if requested_toppings:
for requested_topping in requested_toppings:
print("Adding " + requested_topping + ".")
print("\nFinished making your pizza!")
else:
print("Are you sure you want a plain pizza?")
5.5設定if語句的格式
PEP 8提供的唯一建議是,在諸如== 、>= 和<= 等比較運算子兩邊各新增一個空格
6.字典
類似結構體,類似索引,字典用放在花括號{} 中的一系列鍵—值對錶示。
如果字典中,鍵相同,對應的值是最後一對,而不是累加一起。
alien_0 = {'color': 'green',
'points': 5}
print(alien_0['color'])
print(alien_0['points'])
6.1 使用字典
6.1.1訪問字典中的值
new_points = alien_0['points']
6.1.2新增鍵—值對
字典是一種動態結構,可隨時在其中新增鍵—值對。要新增鍵—值對, 可依次指定字典名、用方括號括起的鍵和相關聯的值。
alien_0 = {'color': 'green', 'points': 5}
print(alien_0)
alien_0['x_position'] = 0
alien_0['y_position'] = 25
print(alien_0)
6.1.3 建立空字典
可使用一對空的花括號定義一個字典
alien_0 = {}
alien_0['color'] = 'green'
alien_0['points'] = 5
print(alien_0)
6.1.4 修改字典中的值
alien_0['color'] = 'yellow'
6.1.5 刪除鍵—值對
對於字典中不再需要的資訊,可使用del 語句將相應的鍵—值對徹底刪除。使用del 語句時,必須指定字典名和要刪除的鍵。
del alien_0['points']
6.1.6 由類似物件組成的字典
字典儲存的是一個物件(遊戲中的一個外星人) 的多種資訊,但你也可以使用字典來儲存眾多物件的同一種資訊。例如,假設你要調查很多人,詢問他們最喜歡的程式語言,可使用一個字典來儲存這種簡單調查的結果
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}
Python中中括號[]、小括號()、花括號{}的說明
python語言最常見的括號有三種,分別是:小括號( )、中括號[ ]和大括號也叫做花括號{ }。其作用也各不相同,分別用來代表不同的python基本內建資料型別。
1 小括號( ):代表tuple元組資料型別,元組是一種不可變序列。 tup = (1,2,3)
2 python中的中括號[ ]:代表list列表資料型別,列表是一種可變的序列 x=[1,2,3,4,5,6,7,8,9,10]
3 python大括號{ }花括號:代表dict字典資料型別,字典是由鍵對值組組成。冒號’:‘分開鍵和值,逗號’,'隔開組。用大括號建立的方法如下: dic={‘jon’:‘boy’,‘lili’:‘girl’}
6.2遍歷字典
6.2.1遍歷所有的鍵—值對
要編寫用於遍歷字典的for 迴圈,使用 item() ,可宣告兩個變數,用於儲存鍵—值對中的鍵和值。對於這兩個變數,可使用任何名稱。
user_0 = {
'username': 'efermi',
'first': 'enrico',
'last': 'fermi',}
for key, value in user_0.items():
print("\nKey: " + key)
print("Value: " + value)
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}
for name, language in favorite_languages.items():
print(name.title() + "'s favorite language is " +
language.title() + ".")
6.2.2遍歷所有的鍵
使用keys() 或者 不使用
for name in favorite_languages.keys():
print(name.title())
如果將上述程式碼中的for name in favorite_languages.keys(): 替換為for name in favorite_languages: ,輸出將不變
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}
friends = ['phil', 'sarah']
for name in favorite_languages.keys():
print(name.title())
if name in friends:
print(" Hi " + name.title() +
", I see your favorite language is " +
favorite_languages[name].title() + "!")
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}
if 'erin' not in favorite_languages.keys():
print("Erin, please take our poll!")
6.2.3按順序遍歷字典中的所有鍵
字典總是明確地記錄鍵和值之間的關聯關係,但獲取字典的元素時,獲取順序是不可預測的。 使用函式sorted() 來獲得按特定順序排列的鍵列表的副本:
for name in sorted(favorite_languages.keys()):
print(name.title() + ", thank you for taking the poll.")
6.2.4遍歷所有的值
使用values()
for language in favorite_languages.values():
print(language.title())
這種做法提取字典中所有的值,而沒有考慮是否重複. 為剔除重複項,可使用集合(set)
for language in set(favorite_languages.values()):
print(language.title())
6.3巢狀
將一系列字典儲存在列表中,或將列表作為值儲存在字典中,這稱為巢狀 。 你可以在列表中巢狀字典、在字典中巢狀列表甚至在字典中巢狀字典。
6.3.1字典列表
列表裡存放字典
alien_0 = {'color': 'green', 'points': 5}
alien_1 = {'color': 'yellow', 'points': 10}
alien_2 = {'color': 'red', 'points': 15}
aliens = [alien_0, alien_1, alien_2]
for alien in aliens:
print(alien)
aliens = []# 建立一個用於儲存外星人的空列表
for alien_number in range(30):# 建立30個綠色的外星人
new_alien = {'color': 'green', 'points': 5, 'speed': 'slow'}
aliens.append(new_alien)
for alien in aliens[:5]:# 顯示前五個外星人
print(alien)
print("...")
print("Total number of aliens: " + str(len(aliens)))# 顯示建立了多少個外星人
6.3.2字典中存放列表
pizza = {# 儲存所點比薩的資訊
'crust': 'thick',
'toppings': ['mushrooms', 'extra cheese'],
}
print("You ordered a " + pizza['crust'] + "-crust pizza " +
"with the following toppings:")# 概述所點的比薩
for topping in pizza['toppings']:
print("\t" + topping)
favorite_languages = {
'jen': ['python', 'ruby'],
'sarah': ['c'],
'edward': ['ruby', 'go'],
'phil': ['python', 'haskell'],
}
for name, languages in favorite_languages.items():
print("\n" + name.title() + "'s favorite languages are:")
for language in languages:
print("\t" + language.title())
6.3.3在字典中儲存字典
users = {
'aeinstein': {
'first': 'albert',
'last': 'einstein',
'location': 'princeton',
},
'mcurie': {
'first': 'marie',
'last': 'curie',
'location': 'paris',
},
}
for username, user_info in users.items():
print("\nUsername: " + username)
full_name = user_info['first'] + " " + user_info['last']
location = user_info['location']
print("\tFull name: " + full_name.title())
print("\tLocation: " + location.title())
7使用者輸入和while迴圈
7.1使用者輸入
1.函式input() 讓程式暫停執行,等待使用者輸入一些文字(字串)
2.使用int() 來獲取數值輸入
age = input("How old are you? ")#1
print(age)
age = int(age)#2
print(age)
7.2while迴圈
1.用法與C語言的類似
2.使用者選擇何時退出
3.使用標誌
4.使用break退出
5.使用continue
current_number = 1
while current_number <= 5:
print(current_number)
current_number += 1
prompt = "\nTell me something, and I will repeat it back to you:"
prompt += "\nEnter 'quit' to end the program. "
message = ""
while message != 'quit':
message = input(prompt)
if message != 'quit':
print(message)
prompt = "\nTell me something, and I will repeat it back to you:"
prompt += "\nEnter 'quit' to end the program. "
active = True
while active:
message = input(prompt)
if message == 'quit':
active = False
else:
print(message)
prompt = "\nPlease enter the name of a city you have visited:"
prompt += "\n(Enter 'quit' when you are finished.) "
while True:
city = input(prompt)
if city == 'quit':
break
else:
print("I'd love to go to " + city.title() + "!")
current_number = 0
while current_number < 10:
current_number += 1
if current_number % 2 == 0:
continue
print(current_number)
7.3使用while迴圈來處理列表和字典
1.列表之間移動元素
2.刪除特定值的元素:使用函式remove()
3.使用者輸入增加元素
''' 首先,建立一個待驗證使用者列表'''
''' 和一個用於儲存已驗證使用者的空列表'''
unconfirmed_users = ['alice', 'brian', 'candace']
confirmed_users = []
''' 驗證每個使用者,直到沒有未驗證使用者為止'''
''' 將每個經過驗證的列表都移到已驗證使用者列表中'''
while unconfirmed_users:
current_user = unconfirmed_users.pop()
print("Verifying user: " + current_user.title())
confirmed_users.append(current_user)
print("\nThe following users have been confirmed:")# 顯示所有已驗證的使用者
for confirmed_user in confirmed_users:
print(confirmed_user.title())
pets = ['dog', 'cat', 'dog', 'goldfish', 'cat', 'rabbit', 'cat']
print(pets)
while 'cat' in pets:
pets.remove('cat')
print(pets)
responses = {}
''' 設定一個標誌,指出調查是否繼續'''
polling_active = True
while polling_active:
''' 提示輸入被調查者的名字和回答'''
name = input("\nWhat is your name? ")
response = input("Which mountain would you like to climb someday? ")
''' 將答卷儲存在字典中'''
responses[name] = response
''' 看看是否還有人要參與調查'''
repeat = input("Would you like to let another person respond? (yes/ no) ")
if repeat == 'no':
polling_active = False
''' 調查結束,顯示結果'''
print("\n--- Poll Results ---")
for name, response in responses.items():
print(name + " would like to climb " + response + ".")
8函式
8.1定義函式
1.使用def 申明是一個函式
2.在括號中向函式傳遞資訊
def greet_user():
"""顯示簡單的問候語"""
print("Hello!")
greet_user()
def greet_user(username):
"""顯示簡單的問候語"""
print("Hello, " + username.title() + "!")
greet_user('jesse')
8.2傳遞實參
1.位置實參(引數順序不能顛倒)
2.關鍵字實參(引數順序無所謂)
3.設定預設值
PS:等號兩邊不要有空格
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('hamster', 'harry')#1
describe_pet('dog', 'willie')
describe_pet(animal_type='hamster', pet_name='harry')#2
describe_pet(pet_name='harry', animal_type='hamster')
In [ ]:
def describe_pet(pet_name, animal_type='dog'):#3
"""顯示寵物的資訊"""
print("\nI have a " + animal_type + ".")
print("My " + animal_type + "'s name is " + pet_name.title() + ".")
describe_pet(pet_name='willie')
describe_pet('willie')
describe_pet(pet_name='harry', animal_type='hamster')
describe_pet('harry', 'hamster')
8.3返回值
1.使用return語句,獲取返回值
2.實參變得可選
3.返回字典
4.函式和while結合
def get_formatted_name(first_name, last_name):
"""返回整潔的姓名"""
full_name = first_name + ' ' + last_name
return full_name.title()
musician = get_formatted_name('jimi', 'hendrix')
print(musician)
def get_formatted_name(first_name, last_name, middle_name=''):
"""返回整潔的姓名"""
if middle_name:
full_name = first_name + ' ' + middle_name + ' ' + last_name
else:
full_name = first_name + ' ' + last_name
return full_name.title()
musician = get_formatted_name('jimi', 'hendrix')
print(musician)
musician = get_formatted_name('john', 'hooker', 'lee')
print(musician)
def build_person(first_name, last_name):
"""返回一個字典,其中包含有關一個人的資訊"""
person = {'first': first_name, 'last': last_name}
return person
musician = build_person('jimi', 'hendrix')
print(musician)
def get_formatted_name(first_name, last_name):
"""返回整潔的姓名"""
full_name = first_name + ' ' + last_name
return full_name.title()
while True:# 這是一個無限迴圈!
print("\nPlease tell me your name:")
print("(enter 'q' at any time to quit)")
f_name = input("First name: ")
if f_name == 'q':
break
l_name = input("Last name: ")
if l_name == 'q':
break
formatted_name = get_formatted_name(f_name, l_name)
print("\nHello, " + formatted_name + "!")
8.4傳遞列表
將列表傳遞給函式後,函式就能直接訪問其內容。下面使用函式來提高處理列表的效率
def greet_users(names):
"""向列表中的每位使用者都發出簡單的問候"""
for name in names:
msg = "Hello, " + name.title() + "!"
print(msg)
usernames = ['hannah', 'ty', 'margot']
greet_users(usernames)
1.在函式中修改列表:在函式中對這個列表所做的任何修改都是永久性的
2.禁止函式修改列表:可向函式傳遞列表的副本而不是原件 function_name(list_name[:])
def print_models(unprinted_designs, completed_models):
"""
模擬列印每個設計,直到沒有未列印的設計為止
列印每個設計後,都將其移到列表completed_models中
"""
while unprinted_designs:
current_design = unprinted_designs.pop()
# 模擬根據設計製作3D列印模型的過程
print("Printing model: " + current_design)
completed_models.append(current_design)
def show_completed_models(completed_models):
"""顯示列印好的所有模型"""
print("\nThe following models have been printed:")
for completed_model in completed_models:
print(completed_model)
unprinted_designs = ['iphone case', 'robot pendant', 'dodecahedron']
completed_models = []
print_models(unprinted_designs, completed_models)
show_completed_models(completed_models)
print_models(unprinted_designs[:], completed_models)
8.5傳遞任意數量的實參
**在引數前面加 ***
def make_pizza(*toppings):
"""概述要製作的比薩"""
print("\nMaking a pizza with the following toppings:")
for topping in toppings:
print("- " + topping)
make_pizza('pepperoni')
make_pizza('mushrooms', 'green peppers', 'extra cheese')
8.5.1結合使用位置實參和任意數量實參
如果要讓函式接受不同型別的實參,必須在函式定義中將接納任意數量實參的形參放在最後。Python先匹配位置實參和關鍵字實參,再將餘下的實參都收集到最後一個形參中
def make_pizza(size, *toppings):
"""概述要製作的比薩"""
print("\nMaking a " + str(size) +
"-inch pizza with the following toppings:")
for topping in toppings:
print("- " + topping)
make_pizza(16, 'pepperoni')
make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
8.5.2 使用任意數量的關鍵字實參
形參** user_info 中的兩個星號讓Python建立一個名為user_info 的空字典
def build_profile(first, last, **user_info):
"""Build a dictionary containing everything we know about a user."""
profile = {}
profile['first_name'] = first
profile['last_name'] = last
for key, value in user_info.items():
profile[key] = value
return profile
user_profile = build_profile('albert', 'einstein',
location='princeton',
field='physics')
print(user_profile)
8.6函式儲存在模組中
類似C語言中,將函式儲存在C檔案中
import語句允許在當前執行的程式檔案中使用模組中的程式碼(C語言中是include)
8.6.1匯入方法
1.匯入整個模組:import module_name
通過module_name.function_name() 來呼叫檔案中的任何一個函式
2.匯入模組中的所有函式:**from module_name import ***
由於匯入了每個函式,可通過名稱來呼叫每個函式,而無需使用句點表示法
然而,使用並非自己編寫的大型模組時,最好不要採用這種匯入方法:如果模組中有函式的名稱與你的專案中使用的名稱相同,可能導致意想不到的結果:Python可能遇到多個名稱相同的函式或變數,進而覆蓋函式,而不是分別匯入所有的函式
3.使用as 給模組指定別名:import module_name as mn
4.匯入特定的函式:from module_name import function_name和
from module_name import function_0, function_1, function_2
5.使用as 給函式指定別名:from module_name import function_name as fn
def make_pizza(size, *toppings):#pizza.py檔案
"""概述要製作的比薩"""
print("\nMaking a " + str(size) +
"-inch pizza with the following toppings:")
for topping in toppings:
print("- " + topping)
'''1.匯入整個模組
making_pizzas.py檔案
'''
import pizza
pizza.make_pizza(16, 'pepperoni')
pizza.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
'''2.匯入模組中的所有函式'''
from pizza import *
make_pizza(16, 'pepperoni')
make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
'''3.使用as 給模組指定別名'''
import pizza as p
p.make_pizza(16, 'pepperoni')
p.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
'''4.匯入特定的函式'''
from pizza import make_pizza
make_pizza(16, 'pepperoni')
make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
'''5.使用as 給函式指定別名'''
from pizza import make_pizza as mp
mp(16, 'pepperoni')
mp(12, 'mushrooms', 'green peppers', 'extra cheese')
9.類
根據類來建立物件被稱為例項化 ,這讓你能夠使用類的例項。
1.編寫一些類並建立其例項。
2.指定可在例項中儲存什麼資訊,定義可對這些例項執行哪些操作。
3.編寫一些類來擴充套件既有類的功能,讓相似的類能夠高效地共享程式碼。
4.把自己編寫的類儲存在模組中,並在自己的程式檔案中匯入其他人編寫的類。
9.1建立和使用類
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()
init() 是一個特殊的方法,每當你根據Dog 類建立新例項時,Python都會自動執行它。在這個方法的名稱中,開頭和末尾各有兩個下劃線,這是一種約定,旨在避免Python預設方法與普通方法發生名稱衝突
方法init() 定義成了包含三個形參:self 、name 和age。形參self 必不可少,還必須位於其他形參的前面。因為Python呼叫這個init() 方法來建立Dog 例項時,將自動傳入實參self 。每個與類相關聯的方法呼叫都自動傳遞實參self ,它是一個指向例項本身的引用,讓例項能夠訪問類中的屬性和方法。
我們將通過實參向Dog() 傳遞名字和年齡;self 會自動傳遞,因此我們不需要傳遞它。每當我們根據Dog 類建立例項時,都只需給最後兩個形參(name 和age)提供值。
定義的兩個變數都有字首self 。以self 為字首的變數都可供類中的所有方法使用,我們還可以通過類的任何例項來訪問這些變數。self.name = name 獲取儲存在形參name 中的值,並將其儲存到變數name 中,然後該變數被關聯到當前建立的例項。像這樣可通過例項訪問的變數稱為屬性 。
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.")
通常可以認為首字母大寫的名稱(如Dog ) 指的是類,而小寫的名稱(如my_dog ) 指的是根據類建立的例項。
Python使用實參’willie’ 和6 呼叫Dog 類中的方法init()
方法**init() **並未顯式地包含return 語句,但Python自動返回一個表示這條小狗的例項。
訪問屬性和呼叫方法:句點法my_dog.name
9.2使用類和例項
9.2.1給屬性指定預設值
class Car():
def __init__(self, make, model, year):
"""初始化描述汽車的屬性"""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def read_odometer(self):
"""列印一條指出汽車裡程的訊息"""
print("This car has " + str(self.odometer_reading) + " miles on it.")
建立一個名為odometer_reading 的屬性,並將其初始值設定為0。還定義了一個名為ead_odometer() 的方法,獲悉汽車的里程。
9.2.2修改屬性值
-
直接修改
my_new_car.odometer_reading = 23
-
通過方法修改
-
通過方法遞增
class Car(): –snip–
def update_odometer(self, mileage): """將里程錶讀數設定為指定的值""" self.odometer_reading = mileage def increment_odometer(self, miles): """將里程錶讀數增加指定的量""" self.odometer_reading += miles
9.3繼承
如果你要編寫的類是另一個現成類的特殊版本,可使用繼承 。一個類繼承 另一個類時,它將自動獲得另一個類的所有屬性和方法;原有的類稱為父類/超類,而新類稱為子類 。子類繼承了其父類的所有屬性和方法,同時還可以定義自己的屬性和方法。
9.3.1子類的方法__init__()
Car類是父類,ElectricCar類是子類,父類必須在子類前面。 定義子類時,必須在括號內指定父類的名稱。方法__init__() 接受建立Car例項所需的資訊。 **super()**函式使父類和子類關聯起來
class Car():
--snip--
class ElectricCar(Car):
"""電動汽車的獨特之處"""
def __init__(self, make, model, year):
"""初始化父類的屬性"""
super().__init__(make, model, year)
9.3.2給子類定義屬性和方法
class Car():
--snip--
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.
其中新加屬性self.battery_size,還新加新方法describe_battery()
9.3.3重寫父類的方法
假設Car類中有一個fill_gas_tank() 的方法,它對全電動汽車來說毫無意義,因此你可能想重寫它。
def ElectricCar(Car):
--snip--
def fill_gas_tank():
"""電動汽車沒有油箱"""
print("This car doesn't need a gas tank!")
9.3.4將例項用做屬性
類中的屬性可以用類來表示 將大型類拆分成多個協同工作的小類。例如,不斷給ElectricCar 類新增細節時,我們可能會發現其中包含很多專門針對汽車電瓶的屬性和方法。在這種情況下,我們可將這些屬性和方法提取出來,放到另一個名為attery 的類中,並將一個Battery 例項用作ElectricCar 類的一個屬性:
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()
在ElectricCar 類中,我們添加了一個名為self.battery 的屬性,建立一個新的Battery例項
PS:
- def init(self, battery_size=70): 左右兩邊是兩條下劃線
- class ElectricCar(Car): 子類類名後面的括號需要填寫父類
- super().init(make, model, year) 繼承父類這部分不要寫self
9.4匯入類
9.4.1匯入單個類
和include差不多,將類單獨寫在一個檔案中,在其他檔案中使用include匯入
在car.py檔案中,只包含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
在my_car.py檔案中,匯入Car類並建立例項:from car import Car
from car import Car
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()
9.4.2在一個模組中儲存多個類
在car.py檔案中,包含Car類,Battery類和ElectricCar類
class Car():
--snip--
class Battery():
"""一次模擬電動汽車電瓶的簡單嘗試"""
def __init__(self, battery_size=60):
"""初始化電瓶的屬性"""
self.battery_size = battery_size
def describe_battery(self):
"""列印一條描述電瓶容量的訊息"""
print("This car has a " + str(self.battery_size) + "-kWh battery.")
def get_range(self):
"""列印一條描述電瓶續航里程的訊息"""
if self.battery_size == 70:
range = 240
elif self.battery_size == 85:
range = 270
message = "This car can go approximately " + str(range)
message += " miles on a full charge."
print(message)
class ElectricCar(Car):
"""模擬電動汽車的獨特之處"""
def __init__(self, make, model, year):
"""
初始化父類的屬性,再初始化電動汽車特有的屬性
"""
super().__init__(make, model, year)
self.battery = Battery()
在my_electric_car.py檔案中,匯入ElectricCar類並建立例項
from car 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從一個模組中匯入多個類
在my_car.py檔案中,匯入Car類和ElectricCar類並建立例項:from car import Car, ElectricCar
from car 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())
PS 匯入多個類時,要用逗號隔開,不能用空格
9.4.4匯入整個模組
匯入整個模組,再使用句點表示法訪問需要的類.在my_car.py檔案中,匯入整個car模組:import car
import car
my_beetle = car.Car('volkswagen', 'beetle', 2016)
print(my_beetle.get_descriptive_name())
my_tesla = car.ElectricCar('tesla', 'roadster', 2016)
print(my_tesla.get_descriptive_name())
9.4.5匯入模組中所有的類
from module_name import *
不推薦使用這種方法
1.不清楚到底匯入了哪些類
2.容易出現同名
9.4.6在一個模組中匯入另一個模組
Car類儲存在一個模組car.py中,並將ElectricCar類和Battery類儲存在另一個模組electric_car.py中
在car.py檔案中
class Car():
--snip--
在electric_car.py檔案中
from car import Car
class Battery():
--snip--
class ElectricCar(Car):
--snip--
在my_cars.py檔案中
from car import Car
from electric_car import 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.5Python標準庫
9.6類編碼風格
類名應採用駝峰命名法 ,即將類名中的每個單詞的首字母都大寫,而不使用下劃線。例項名和模組名都採用小寫格式,並在單詞之間加上下劃線
對於每個類,都應緊跟在類定義後面包含一個文件字串
在類中,可使用一個空行來分隔方法;而在模組中,可使用兩個空行來分隔類
需要同時匯入標準庫中的模組和你編寫的模組時,先編寫匯入標準庫模組的import 語句,再新增一個空行,然後編寫匯入你自己編寫的模組的import 語句
10檔案和異常
pi_digits.txt檔案中 3.1415926535 8979323846 2643383279
10.1從檔案中讀取資料
with open('pi_digits.txt') as file_object:
contents = file_object.read()
print(contents)
函式open() 接受一個引數:要開啟的檔案的名稱。Python在當前執行的檔案所在的目錄中查詢指定的檔案
關鍵字with 在不再需要訪問檔案後將其關閉,可讓Python去確定:你只管開啟檔案,並在需要時使用它,Python自會在合適的時候自動將其關閉。
也可以使用open()和close()函式操作檔案開啟和關閉
末尾多了一個空行。為何會多出這個空行呢?因為read() 到達檔案末尾時返回一個空字串,而將這個空字串顯示出來時就是一個空行。要刪除多出來的空行,可在print 語句中使用rstrip()
10.1.2檔案路徑
相對路徑 絕對路徑
10.1.3逐行讀取
filename = 'pi_digits.txt'
with open(filename) as file_object:
for line in file_object:
print(line.rstrip())
10.1.4建立一個包含檔案各行內容的列表
readlines() 從檔案中讀取每一行,並將其儲存在一個列表中
filename = 'pi_digits.txt'
with open(filename) as file_object:
lines = file_object.readlines()
for line in lines:
print(line.rstrip())
10.1.5使用檔案的內容
filename = 'pi_digits.txt'
with open(filename) as file_object:
lines = file_object.readlines()
pi_string = ''
for line in lines:
pi_string += line.rstrip()
print(pi_string)
print(len(pi_string))
10.1.6包含一百萬位的大型檔案
filename = 'pi_million_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] + "...")
print(len(pi_string))
10.1.7圓周率包含你的生日嗎
if birthday in pi_string:
filename = 'pi_million_digits.txt'
with open(filename) as file_object:
lines = file_object.readlines()
pi_string = ''
for line in lines:
pi_string += line.rstrip()
birthday = input("Enter your birthday, in the form mmddyy: ")
if birthday in pi_string:
print("Your birthday appears in the first million digits of pi!")
else:
print("Your birthday does not appear in the first million digits of pi.")
10.2寫入檔案
10.2.1 寫入空檔案
Python只能將字串寫入文字檔案
filename = 'programming.txt'
with open(filename, 'w') as file_object:
file_object.write("I love programming.")
10.2.2 寫入多行
filename = 'programming.txt'
with open(filename, 'w') as file_object:
file_object.write("I love programming.\n")
file_object.write("I love creating new games.\n")
10.2.3 附加到檔案
filename = 'programming.txt'
with open(filename, 'a') as file_object:
file_object.write("I also love finding meaning in large datasets.\n")
file_object.write("I love creating apps that can run in a browser.\n")
10.3 異常
Python使用被稱為異常 的特殊物件來管理程式執行期間發生的錯誤。 每當發生讓Python不知所措的錯誤時,它都會建立一個異常物件。 如果你編寫了處理該異常的程式碼,程式將繼續執行;如果你未對異常進行處理,程式將停止,並顯示一個traceback,其中包含有關異常的報告。
10.3.1處理ZeroDivisionError 異常
print(5/0)
10.3.2 try-except 程式碼塊
try:
print(5/0)
except ZeroDivisionError:
print("You can't divide by zero!")
10.3.3 try-except-els 程式碼塊
print("Give me two numbers, and I'll divide them.")
print("Enter 'q' to quit.")
while True:
first_number = input("\nFirst number: ")
if first_number == 'q':
break
second_number = input("Second number: ")
try:
answer = int(first_number) / int(second_number)
except ZeroDivisionError:
print("You can't divide by 0!")
else:
print(answer)
10.3.4 處理FileNotFoundError 異常
找不到檔案
filename = 'alice.txt'
with open(filename) as f_obj:
contents = f_obj.read()
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)
10.3.5 分析文字
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.")
10.3.6 使用多個檔案
def count_words(filename):
"""計算一個檔案大致包含多少個單詞"""
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.")
filenames = ['alice.txt', 'siddhartha.txt', 'moby_dick.txt', 'little_women.txt']
for filename in filenames:
count_words(filename)
10.3.7 失敗時一聲不吭
except FileNotFoundError:
pass
10.4 儲存資料
10.4.1 使用json.dump() 和json.load()
import json
numbers = [2, 3, 5, 7, 11, 13]
filename = 'numbers.json'
with open(filename, 'w') as f_obj:
json.dump(numbers, f_obj)
import json
filename = 'numbers.json'
with open(filename) as f_obj:
numbers = json.load(f_obj)
print(numbers)
10.4.2 重構
程式碼能夠正確地執行,但可做進一步的改進——將程式碼劃分為一系列完成具體工作的函式
11測試程式碼
使用Python模組unittest 中的工具來測試程式碼
11.1 測試函式
11.1.1 單元測試和測試用例
單元測試 用於核實函式的某個方面沒有問題;
測試用例 是一組單元測試,這些單元測試一起核實函式在各種情形下的行為都符合要求
name_function.py檔案
def get_formatted_name(first, last):
"""Generate a neatly formatted full name."""
full_name = first + ' ' + last
return full_name.title()
11.1.2 可通過的測試
要為函式編寫測試用例,可先匯入模組unittest 以及要測試的函式,
再建立一個繼承unittest.TestCase 的類,並編寫一系列方法對函式行為的不同方面進行測試。
test_name_function.py檔案
import unittest
from name_function import get_formatted_name
class NamesTestCase(unittest.TestCase):
"""測試name_function.py"""
def test_first_last_name(self):
"""能夠正確地處理像Janis Joplin這樣的姓名嗎?"""
formatted_name = get_formatted_name('janis', 'joplin')
self.assertEqual(formatted_name, 'Janis Joplin')
unittest.main()
11.1.3 不能通過的測試
name_function.py檔案
def get_formatted_name(first, middle, last):
"""生成整潔的姓名"""
full_name = first + ' ' + middle + ' ' + last
return full_name.title()
11.1.4 測試未通過時怎麼辦
name_function.py檔案
def get_formatted_name(first, last, middle=''):
"""生成整潔的姓名"""
if middle:
full_name = first + ' ' + middle + ' ' + last
else:
full_name = first + ' ' + last
return full_name.title()
11.1.5 新增新測試
test_name_function.py檔案
import unittest
from name_function import get_formatted_name
class NamesTestCase(unittest.TestCase):
"""測試name_function.py """
def test_first_last_name(self):
"""能夠正確地處理像Janis Joplin這樣的姓名嗎?"""
formatted_name = get_formatted_name('janis', 'joplin')
self.assertEqual(formatted_name, 'Janis Joplin')
def test_first_last_middle_name(self):
"""能夠正確地處理像Wolfgang Amadeus Mozart這樣的姓名嗎?"""
formatted_name = get_formatted_name('wolfgang', 'mozart', 'amadeus')
self.assertEqual(formatted_name, 'Wolfgang Amadeus Mozart')
unittest.main()
11.2 測試類
11.2.1 各種斷言方法
方法 | 用途 |
---|---|
assertEqual(a, b) | 核實a == b |
assertNotEqual(a, b) | 核實a != b |
assertTrue(x) | 核實x 為True |
assertFalse(x) | 核實x 為False |
assertIn(item , list ) | 核實 item 在 list 中 |
assertNotIn(item , list ) | 核實 item 不在 list 中 |
11.2.4 方法setUp()
使用setUp() 來建立一個調查物件和一組答案, 供方法test_store_single_response() 和 test_store_three_responses() 使用
import unittest
from survey import AnonymousSurvey
class TestAnonymousSurvey(unittest.TestCase):
"""針對AnonymousSurvey類的測試"""
def setUp(self):
"""
建立一個調查物件和一組答案,供使用的測試方法使用
"""
question = "What language did you first learn 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_responses(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() 做了兩件事情:建立一個調查物件;建立一個答案列表
PS 執行測試用例時,每完成一個單元測試,Python都列印一個字元:測試通過時列印一個句點;測試引發錯誤時列印一個E ;測試導致斷言失敗時列印一個F 。這就是你執行測試用例時,在輸出的第一行中看到的句點和字元數量各不相同的原因。