1. 程式人生 > >python learning

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修改屬性值

  1. 直接修改

    my_new_car.odometer_reading = 23

  2. 通過方法修改

  3. 通過方法遞增

    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

  1. def init(self, battery_size=70): 左右兩邊是兩條下劃線
  2. class ElectricCar(Car): 子類類名後面的括號需要填寫父類
  3. 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 。這就是你執行測試用例時,在輸出的第一行中看到的句點和字元數量各不相同的原因。