備註:如下按照Python 2的規則編寫代碼。
在jupyter notebook中運行直接顯示結果。python
"""10.1.1 讀取整個文件"""
"""file_reader.py"""
with open('chapter_10/pi_digits.txt') as file_object: # 關鍵字with在再也不須要訪問文件後將其關閉
contents = file_object.read()
print(contents)
3.1415926535 8979323846 2643383279
"""10.1.1 讀取整個文件"""
"""file_reader.py"""
with open('chapter_10/pi_digits.txt') as file_object: # 關鍵字with在再也不須要訪問文件後將其關閉
contents = file_object.read()
print(contents.rstrip()) # 使用rstrip()刪除文件末尾多餘的空行
3.1415926535 8979323846 2643383279
"""10.1.3 逐行讀取"""
"""file_reader.py"""
filename = 'chapter_10/pi_digits.txt'
with open(filename) as f:
for line in f:
print line
with open(filename) as f:
for line in f:
print line.rstrip()
3.1415926535 8979323846 2643383279 3.1415926535 8979323846 2643383279
"""10.1.4 建立包含文件各行內容的列表"""
filename = 'chapter_10/pi_digits.txt'
with open(filename) as f:
lines = f.readlines()
print lines
for line in lines:
print line.rstrip()
['3.1415926535\n', ' 8979323846\n', ' 2643383279\n'] 3.1415926535 8979323846 2643383279
"""10.1.5 使用文件中的內容"""
"""pi_string.py"""
filename = 'chapter_10/pi_digits.txt'
with open(filename) as f:
lines = f.readlines()
pi_string = ''
for line in lines:
pi_string += line.rstrip()
print pi_string
print len(pi_string)
3.1415926535 8979323846 2643383279 36
"""10.1.5 使用文件中的內容"""
"""pi_string.py"""
filename = 'chapter_10/pi_digits.txt'
with open(filename) as f:
lines = f.readlines()
pi_string = ''
for line in lines:
pi_string += line.strip() # 刪除先後的空格
print pi_string
print len(pi_string)
3.141592653589793238462643383279 32
讀取文本文件時,Python將其中的全部文本都解讀爲字符串。若是讀取的是數字,並要將其做爲數值使用,就必須使用函數int()將其轉換爲整數,或使用函數float()將其轉換爲浮點數。git
"""10.1.6 包含一百萬位的大型文件 """
"""pi_string.py"""
filename = 'chapter_10/pi_million_digits.txt'
with open(filename) as f:
lines = f.readlines()
pi_string = ''
for line in lines:
pi_string += line.strip()
print pi_string[:52] + "..." # 以打印小數點後50位爲例
print len(pi_string)
3.14159265358979323846264338327950288419716939937510... 1000002
"""10.1.7 圓周率值中包含你的生日嗎 """
"""任務:肯定某個生日是否包含在圓周率值的前1 000 000位中。"""
filename = 'chapter_10/pi_million_digits.txt'
with open(filename) as f:
lines = f.readlines()
pi_string = ''
for line in lines:
pi_string += line.rstrip()
birthday = raw_input("Enter your birthday, in the form mmddyy: ")
if birthday in pi_string:
print "Your birthday aperars in the first million digits of pi!"
else:
print "Your birthday doesn't appear in the first million digits of pi."
Enter your birthday, in the form mmddyy: 120372 Your birthday aperars in the first million digits of pi!
"""10-1 Python學習筆記"""
""" 在文本編輯器中新建一個文件,寫幾句話來總結一下你至此學到的 Python 知識,其中每一行都以「In Python you can」打頭。 將這文件命名爲learning_python.txt,並將其存儲到爲完成本章練習而編寫的程序所在的目錄中。編寫一個程序,它讀取這個 文件,並將你所寫的內容打印三次:第一次打印時讀取整個文件;第二次打印時遍歷文件對象;第三次打印時將各行存儲在一個列 表中,再在 with 代碼塊外打印它們。 """
with open('chapter_10/learning_python.txt') as lp:
contents = lp.read()
print "1>>>"
print contents
print "\n2>>>"
for line in contents:
print line.strip()
print "\n3>>>"
with open('chapter_10/learning_python.txt') as lp:
lines = lp.readlines()
for line in lines:
print line.rstrip()
1>>> In Python you can do whatever you want! In Python you can read different tpyes of files. In Python you can draw something. In Python you can program interesting games. 2>>> I n P y t h o n y o u c a n d o w h a t e v e r y o u w a n t ! I n P y t h o n y o u c a n r e a d d i f f e r e n t t p y e s o f f i l e s . I n P y t h o n y o u c a n d r a w s o m e t h i n g . I n P y t h o n y o u c a n p r o g r a m i n t e r e s t i n g g a m e s . 3>>> In Python you can do whatever you want! In Python you can read different tpyes of files. In Python you can draw something. In Python you can program interesting games.
"""10-2 C語言學習筆記"""
""" 讀取你剛建立的文件 learning_python.txt 中的每一行,使用方法replace()將其中的 Python 都替換爲另外一門語言的名稱, 如 C。將修改後的各行都打印到屏幕上。 """
message = "I really like dogs."
message.replace('dog', 'cat')
with open('chapter_10/learning_python.txt') as f:
contents = f.read()
print contents
print "\nChange 'Python' to 'C'."
print contents.replace("Python", "C") # replace()替換字符串中特定單詞
In Python you can do whatever you want! In Python you can read different tpyes of files. In Python you can draw something. In Python you can program interesting games. Change 'Python' to 'C'. In C you can do whatever you want! In C you can read different tpyes of files. In C you can draw something. In C you can program interesting games.
"""10.2.1 寫入空文件"""
"""write_message.py"""
filename = 'chapter_10/programming1.txt'
with open(filename, 'w') as f:
f.write("I love programming.")
# 驗證
with open(filename) as f:
print "The following are in the file:"
print f.read()
The following are in the file: I love programming.
打開文件時,可指定讀取模式(’r’)、寫入模式(’w’)、附加模式(’a’)或讓你可以讀取和寫入文件的模式(’r+’)。若是省略了模式實參,Python將以默認的只讀模式打開文件。編程
若是要寫入的文件不存在,函數open()將自動建立它。然而,以寫入(’w’)模式打開文件時千萬要當心,由於若是指定的文件已經存在,Python將在返回文件對象前清空該文件。json
Python只能將字符串寫入文本文件。要將數值數據存儲到文本文件中,必須先使用函數str()將其轉換爲字符串格式。markdown
"""10.2.2 寫入多行"""
filename = 'chapter_10/programming2.txt'
with open(filename, 'w') as f:
f.write("I love programming.\n") # 插入換行符,不然這兩句會連在一塊兒
f.write("I love creating new games.\n")
# 驗證
with open(filename) as f:
print "The following are in the file:"
print f.read()
The following are in the file: I love programming. I love creating new games.
"""10.2.3 附加到文件"""
""" 若是要給文件添加內容,而不是覆蓋原有的內容,能夠附加模式打開文件,寫入到文件的行都將添加到文件末尾。 若是指定的文件不存在,Python將建立一個空文件。 """
filename = 'chapter_10/programming3.txt'
with open(filename, 'a') as f:
f.write("I also love finding meaning in large dataset.\n")
f.write("I love creating apps that can run in browser.\n")
# 驗證
with open(filename) as f:
print "The following are in the file:"
print f.read()
The following are in the file: I love programming. I love creating new games. I also love finding meaning in large dataset. I love creating apps that can run in browser.
"""10-3 訪客"""
""" 編寫一個程序,提示用戶輸入其名字;用戶做出響應後,將其名字寫入到文件 guest.txt 中。 """
filename = "chapter_10/guest.txt"
name = raw_input("Hello!\nWhat's your name?\n")
with open(filename, "w") as f:
f.write(name)
# 驗證
with open(filename) as f:
print "The following are in the file:"
print f.read()
Hello! What's your name? Dan The following are in the file: Dan
"""10-4 訪客名單"""
""" 編寫一個 while 循環,提示用戶輸入其名字。用戶輸入其名字後,在屏幕上打印一句問候語,並將一條訪問記錄添加到文件 guest_book.txt 中。確保這個文件中的每條記錄都獨佔一行。 """
filename = "chapter_10/guest_book.txt"
name = ""
with open(filename, "a") as f:
while name != "quit":
print "Enter 'quit' to quit this program."
name = raw_input("Please write down your name: ")
if name == "quit":
break
line = "Hello! " + name + "\n"
f.write(line)
print line
Enter 'quit' to quit this program. Please write down your name: Ann Hello! Ann Enter 'quit' to quit this program. Please write down your name: Bob Hello! Bob Enter 'quit' to quit this program. Please write down your name: Candy Hello! Candy Enter 'quit' to quit this program. Please write down your name: Denny Hello! Denny Enter 'quit' to quit this program. Please write down your name: quit
"""10.3.1 ZeroDivisionError 異常"""
"""division.py"""
print 5/0
--------------------------------------------------------------------------- ZeroDivisionError Traceback (most recent call last) <ipython-input-6-8c4a85b4b7dc> in <module>() 2 """division.py""" 3 ----> 4 print 5/0 ZeroDivisionError: integer division or modulo by zero
在上述traceback中,錯誤ZeroDivisionError是一個異常對象。Python沒法按你的要求作時,就會建立這種對象。在這種狀況下,Python將中止運行程序,並指出引起了哪一種異常,而咱們可根據這些信息對程序進行修改。數據結構
下面咱們將告訴Python,發生這種錯誤時怎麼辦;這樣,若是再次發生這樣的錯誤,咱們就有備無患了。app
"""10.3.2 使用try-except代碼塊"""
"""處理ZeroDivisionError異常的try-except代碼塊相似於下面這樣: """
try:
print 5/0
except ZeroDivisionError:
print "You can't divide by zero!"
You can't divide by zero!
在這個示例中,try代碼塊中的代碼引起了ZeroDivisionError異常,所以Python指出了該如何解決問題的except代碼塊,並運行其中的代碼。這樣,用戶看到的是一條友好的錯誤消息,而不是traceback。編程語言
"""10.3.3 使用異常避免崩潰 """
""" 發生錯誤時,若是程序還有工做沒有完成,妥善地處理錯誤就尤爲重要。這種狀況常常會出如今要求用戶提供輸入的程序中; 若是程序可以妥善地處理無效輸入,就能再提示用戶提供有效輸入,而不至於崩潰。 下面來建立一個只執行除法運算的簡單計算器: """
"""division.py"""
print "Give me two numbers, and I'll divide them."
print "Enter 'q' to quit."
while True:
first_number = raw_input("\nFirst number: ")
if first_number == 'q':
break
second_number = raw_input("Second number: ")
if second_number == 'q':
break
answer = float(first_number) / float(second_number)
print(answer)
Give me two numbers, and I'll divide them. Enter 'q' to quit. First number: 5 Second number: 0 --------------------------------------------------------------------------- ZeroDivisionError Traceback (most recent call last) <ipython-input-11-32d5fd3de975> in <module>() 17 if second_number == 'q': 18 break ---> 19 answer = float(first_number) / float(second_number) 20 print(answer) ZeroDivisionError: float division by zero
程序崩潰可很差,但讓用戶看到traceback也不是好主意。不懂技術的用戶會被它們搞糊塗,並且若是用戶懷有惡意,他會經過traceback獲悉你不但願他知道的信息。例如,他將知道你的程序文件的名稱,還將看到部分不能正確運行的代碼。有時候,訓練有素的攻擊者可根據這些信息判斷出可對你的代碼發起什麼樣的攻擊。編輯器
"""10.3.4 else 代碼塊 """
""" 經過將可能引起錯誤的代碼放在try-except代碼塊中,可提升這個程序抵禦錯誤的能力。錯誤是執行除法運算的代碼行致使的, 所以咱們須要將它放到try-except代碼塊中。這個示例還包含一個else代碼塊;依賴於try代碼塊成功執行的代碼都應放到 else代碼塊中: """
print "Give me two numbers, and I'll divide them."
print "Enter 'q' to quit."
while True:
first_number = raw_input("\nFirst number: ")
if first_number == 'q':
break
second_number = raw_input("Second number: ")
#if second_number == 'q':
#break
try:
answer = float(first_number) / float(second_number)
except ZeroDivisionError:
print "You can't divide by 0!"
else:
print(answer)
Give me two numbers, and I'll divide them. Enter 'q' to quit. First number: 5 Second number: 0 You can't divide by 0! First number: 5 Second number: 2 2.5 First number: q
try-except-else代碼塊的工做原理大體以下:Python嘗試執行try代碼塊中的代碼;except代碼塊告訴Python,若是它嘗試運行try代碼塊中的代碼時引起了指定的異常,該怎麼辦。ide
經過預測可能發生錯誤的代碼,可編寫健壯的程序,它們即使面臨無效數據或缺乏資源,也能繼續運行,從而可以抵禦無心的用戶錯誤和惡意的攻擊。
"""10.3.5 處理 FileNotFoundError 異常 """
""" 使用文件時,一種常見的問題是找不到文件:你要查找的文件可能在其餘地方、文件名可能不正確或者這個文件根本就不存在。 對於全部這些情形,均可使用try-except代碼塊以直觀的方式進行處理。 咱們來嘗試讀取一個不存在的文件。下面的程序嘗試讀取文件alice.txt的內容,但我沒有將這個文件存儲在alice.py 所在的目錄中: """
"""alice.py"""
filename = 'alice.txt'
with open(filename) as f_obj:
contents = f_obj.read()
--------------------------------------------------------------------------- IOError Traceback (most recent call last) <ipython-input-14-69c4fe15fe12> in <module>() 10 filename = 'alice.txt' 11 ---> 12 with open(filename) as f_obj: 13 contents = f_obj.read() IOError: [Errno 2] No such file or directory: 'alice.txt'
在這個示例中,這個錯誤是函數open()致使的,所以要處理這個錯誤,必須將try語句放在包含open()的代碼行以前:
filename = 'alice.txt'
try:
with open(filename) as f_obj:
contents = f_obj.read()
except IOError:
msg = "Sorry, the file '" + filename + "' does not exist."
print msg
Sorry, the file 'alice.txt' does not exist.
"""10.3.6 分析文本 """
""" 下面來提取童話Alice in Wonderland的文本,並嘗試計算它包含多少個單詞。咱們將使用方法split(), 它根據一個字符串建立一個單詞列表。 """
filename = 'chapter_10/alice.txt'
try:
with open(filename) as f:
contents = f.read()
except IOError:
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."
The file 'chapter_10/alice.txt' has about 29461 words.
"""10.3.7 使用多個文件 """
""" 下面多分析幾本書。這樣作以前,咱們先將這個程序的大部分代碼移到一個名爲count_words()的函數中, 這樣對多本書進行分析時將更容易: """
"""word_count.py """
def count_words(filename):
"""計算一個文件大體包含多少個單詞"""
try:
with open(filename) as f_obj:
contents = f_obj.read()
except IOError:
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 = ['chapter_10/alice.txt', 'chapter_10/siddhartha.txt', 'chapter_10/moby_dick.txt', 'chapter_10/little_women.txt']
for filename in filenames:
count_words(filename)
The file 'chapter_10/alice.txt' has about 29461 words. Sorry, the file 'chapter_10/siddhartha.txt' does not exist. The file 'chapter_10/moby_dick.txt' has about 215136 words. The file 'chapter_10/little_women.txt' has about 189079 words.
文件siddhartha.txt不存在,但這絲絕不影響這個程序處理其餘文件。
在這個示例中,使用try-except
代碼塊提供了兩個重要的優勢:
若是不捕獲因找不到siddhartha.txt而引起IOError
異常,用戶將看到完整的traceback,而程序將在嘗試分析Siddhartha後中止運行——根本不分析Moby Dick和Little Women。
"""10.3.8 失敗時一聲不吭 """
""" 在前一個示例中,咱們告訴用戶有一個文件找不到。但並不是每次捕獲到異常時都須要告訴用戶,有時候你但願程序在發生異常時 一聲不吭,就像什麼都沒有發生同樣繼續運行。要讓程序在失敗時一聲不吭,可像一般那樣編寫try代碼塊,但在except代碼塊 中明確地告訴Python什麼都不要作。Python有一個pass語句,可在代碼塊中使用它來讓Python什麼都不要作: """
def count_words(filename):
"""計算一個文件大體包含多少個單詞"""
try:
with open(filename) as f_obj:
contents = f_obj.read()
except IOError:
pass
else:
# 計算文件大體包含多少個單詞
words = contents.split()
num_words = len(words)
print "The file '" + filename + "' has about " + str(num_words) + " words."
filenames = ['chapter_10/alice.txt', 'chapter_10/siddhartha.txt', 'chapter_10/moby_dick.txt', 'chapter_10/little_women.txt']
for filename in filenames:
count_words(filename)
The file 'chapter_10/alice.txt' has about 29461 words. The file 'chapter_10/moby_dick.txt' has about 215136 words. The file 'chapter_10/little_women.txt' has about 189079 words.
pass語句還充當了佔位符,它提醒你在程序的某個地方什麼都沒有作,而且之後也許要在這裏作些什麼。
例如,在這個程序中,咱們可能決定將找不到的文件的名稱寫入到文件missing_files.txt中。用戶看不到這個文件,但咱們能夠讀取這個文件,進而處理全部文件找不到的問題。
""" 10-6 加法運算:提示用戶提供數值輸入時,常出現的一個問題是,用戶提供的是文本而不是數字。在這種狀況下,當你嘗試 將輸入轉換爲整數時,將引起 TypeError 異常。編寫一個程序,提示用戶輸入兩個數字,再將它們相加並打印結果。在用戶 輸入的任何一個值不是數字時都捕獲 TypeError 異常,並打印一條友好的錯誤消息。對你編寫的程序進行測試:先輸入兩個 數字,再輸入一些文本而不是數字。 """
print "Give me two numbers, and I'll add them."
num_1 = raw_input("First number: ")
num_2 = raw_input("Second number: ")
try:
sum = float(num_1) + float(num_2)
except ValueError:
print "\nYou didn't give me two NUMBERS!"
else:
print "\nThe answer is: " + str(sum)
Give me two numbers, and I'll add them. First number: 1.2 Second number: 4.3 The answer is: 5.5
""" 10-7 加法計算器:將你爲完成練習 10-6 而編寫的代碼放在一個 while 循環中,讓用戶犯錯(輸入的是文本而不是數字) 後可以繼續輸入數字。 """
print "Give me two numbers, and I'll add them."
print "Enter 'q' to quit."
check = True
while check:
num_1 = raw_input("\nFirst number: ")
if num_1 == "q":
break
num_2 = raw_input("Second number: ")
if num_2 == "q":
break
try:
sum = float(num_1) + float(num_2)
except ValueError:
print "\nYou didn't give me two NUMBERS!"
continue
else:
print "\nThe answer is: " + str(sum)
check = False
Give me two numbers, and I'll add them. Enter 'q' to quit. First number: d Second number: g You didn't give me two NUMBERS! First number: 3 Second number: o You didn't give me two NUMBERS! First number: 7 Second number: 6 The answer is: 13.0
""" 10-8 貓和狗: 建立兩個文件 cats.txt 和 dogs.txt,在第一個文件中至少存儲三隻貓的名字,在第二個文件中至少存儲三條狗的名字。 編寫一個程序,嘗試讀取這些文件,並將其內容打印到屏幕上。將這些代碼放在一個 try-except 代碼塊中,以便在文件不 存在時捕獲 FileNotFound 錯誤,並打印一條友好的消息。將其中一個文件移到另外一個地方,並確認 except 代碼塊中的 代碼將正確地執行。 """
catsname = "chapter_10/cats.txt"
dogsname = "chapter_10/dogs.txt"
def readfile(filename):
try:
with open(filename) as f:
print filename.upper()
print f.read()
except IOError:
print "The '" + filename + "' does not exist!"
readfile(catsname)
readfile(dogsname)
The 'chapter_10/cats.txt' does not exist! The 'chapter_10/dogs.txt' does not exist!
""" 10-9 沉默的貓和狗:修改你在練習 10-8 中編寫的 except 代碼塊,讓程序在文件不存在時一聲不響。 """
catsname = "chapter_10/cats.txt"
dogsname = "chapter_10/dogs.txt"
def readfile(filename):
try:
with open(filename) as f:
print filename.upper()
print f.read()
except IOError:
pass
print "Complete."
readfile(catsname)
readfile(dogsname)
Complete. Complete.
模塊json
讓你可以將簡單的Python數據結構轉儲到文件中,並在程序再次運行時加載該文件中的數據。你還可使用json
在Python程序之間分享數據。
更重要的是,JSON數據格式並不是Python專用的,這讓你可以將以JSON格式存儲的數據與使用其餘編程語言的人分享。這是一種輕便格式,頗有用,也易於學習。
函數json.dump()接受兩個實參:要存儲的數據以及可用於存儲數據的文件對象。
"""number_write.py"""
import json # 導入json模塊
numbers = [2, 3, 5, 7, 11, 13]
filename = 'chapter_10/numbers.json'
with open(filename, 'w') as f:
json.dump(numbers, f)
"""number_reader.py"""
filename = 'chapter_10/numbers.json'
with open(filename) as f:
numbers = json.load(f)
print numbers
[2, 3, 5, 7, 11, 13]
"""存儲用戶的名字"""
"""remember_me.py"""
import json
username = raw_input("What's your name? ")
filename = "chapter_10/username.json"
with open(filename, "w") as f:
json.dump(username, f)
print "We'll remember you when you come back, " + username + "!"
What's your name? Eric We'll remember you when you come back, Eric!
"""再編寫一個程序,向其名字被存儲的用戶發出問候: """
"""greet_user.py """
import json
filename = "chapter_10/username.json"
with open(filename) as f:
username = json.load(f)
print "Welcome back, " + username + "!"
Welcome back, Eric!
"""合併兩個文件"""
"""remember_me.py"""
import json
# 若是之前存儲了用戶名,就加載它
# 不然,就提示用戶輸入用戶名並存儲它
filename = "chapter_10/username.json"
try:
with open(filename) as f:
username = json.load(f)
except IOError:
username = raw_input("What's your name? ")
with open(filename, "w") as f:
json.dump(username, f)
print "We'll remember you when you come back, " + username + "!"
else:
print "Welcome back, " + username + "!"
Welcome back, Eric!
""" 10.4.3 重構 你常常會遇到這樣的狀況:代碼可以正確地運行,但可作進一步的改進——將代碼劃分爲一系列完成具體工做的函數。這樣的過程 被稱爲重構。重構讓代碼更清晰、更易於理解、更容易擴展。 要重構remember_me.py,可將其大部分邏輯放到一個或多個函數中。remember_me.py的重點是問候用戶,所以咱們將其所 有代碼都放到一個名爲greet_user()的函數中: """
"""remrember_me.py"""
def greet_user():
"""問候用戶,並指出其名字"""
filename = "chapter_10/username.json"
try:
with open(filename) as f:
username = json.load(f)
except IOError:
username = raw_input("What's your name? ")
with open(filename, "w") as f:
json.dump(username, f)
print "We'll remember you when you come back, " + username + "!"
else:
print "Welcome back, " + username + "!"
greet_user()
Welcome back, Eric!
""" 下面來重構greet_user(),讓它不執行這麼多任務。爲此,咱們首先將獲取存儲的用戶名的代碼移到另外一個函數中: """
import json
def get_stored_username():
"""若是存儲了用戶名,就獲取它"""
filename = "chapter_10/username.json"
try:
with open(filename) as f:
username = json.load(f)
except IOError:
return None
else:
return username
def greet_user():
username = get_stored_username()
if username:
print "Welcome back, " + username + "!"
else:
username = raw_input("What's your name? ")
with open(filename, "w") as f:
json.dump(username, f)
print "We'll remember you when you come back, " + username + "!"
greet_user()
Welcome back, Eric!
""" 咱們還需將greet_user()中的另外一個代碼塊提取出來:將沒有存儲用戶名時提示用戶輸入的代碼放在一個獨立的函數中: """
import json
def get_stored_username():
try:
with open(filename) as f:
username = json.load(f)
except IOError:
return None
else:
return username
def get_new_username():
"""提示用戶輸入用戶名"""
username = raw_input("What is your name? ")
filename = "chapter_10/username.json"
with open(filename, 'w') as f:
json.dump(username, f)
return username
def greet_user():
username = get_stored_username()
if username:
print "Welcome back, " + username + "!"
else:
username = get_new_username()
print "We'll remember you when you come back, " + username + "!"
greet_user()
Welcome back, Eric!
在remember_me.py的這個最終版本中,每一個函數都執行單一而清晰的任務。
咱們調用greet_user()
,它打印一條合適的消息:要麼歡迎老用戶回來,要麼問候新用戶。
爲此,它首先調用get_stored_username()
,這個函數只負責獲取存儲的用戶名(若是存儲了的話),再在必要時調用get_new_username()
,這個函數只負責獲取並存儲新用戶的用戶名。要編寫出清晰而易於維護和擴展的代碼,這種劃分工做必不可少。
""" 10-11 喜歡的數字:編寫一個程序,提示用戶輸入他喜歡的數字,並使用json.dump()將這個數字存儲到文件中。 再編寫一個程序,從文件中讀取這個值,並打印消息「I know your favorite number! It’s _____.」。 """
import json
filename = "chapter_10/favorite_number.json"
num = raw_input("What's your favorite number? ")
with open(filename, "w") as f:
json.dump(num, f)
with open(filename) as f:
answer = json.load(f)
print "I know your favorite number! It's " + str(answer) + "."
What's your favorite number? 20 I know your favorite number! It's 20.
""" 10-12 記住喜歡的數字:將練習 10-11 中的兩個程序合而爲一。若是存儲了用戶喜歡的數字,就向用戶顯示它, 不然提示用戶輸入他喜歡的數字並將其存儲到文件中。運行這個程序兩次,看看它是否像預期的那樣工做。 """
import json
filename = "chapter_10/favorite_number.json"
with open(filename) as f:
try:
answer = json.load(f)
print "I know your favorite number! It's " + str(answer) + "."
except ValueError:
print "Oh, I don't know your favorite number."
num = raw_input("So what's your favorite number? ")
with open(filename, "w") as f:
json.dump(num, f)
I know your favorite number! It's 20.
""" 10-13 驗證用戶:最後一個 remember_me.py 版本假設用戶要麼已輸入其用戶名,要麼是首次運行該程序。咱們應修改 這個程序,以應對這樣的情形:當前和最後一次運行該程序的用戶並不是同一我的。 爲此,在 greet_user()中打印歡迎用戶回來的消息前,先詢問他用戶名是不是對的。 若是不對,就調用 get_new_username()讓用戶輸入正確的用戶名。 """
import json
def get_stored_username():
filename = "chapter_10/username.json"
try:
with open(filename) as f:
username = json.load(f)
except IOError:
return None
else:
return username
def get_new_username():
"""提示用戶輸入用戶名"""
username = raw_input("What is your name ? ")
filename = "chapter_10/username.json"
with open(filename, 'w') as f:
json.dump(username, f)
return username
def greet_user():
username = get_stored_username()
if username:
check = raw_input("Are you " + username + " ? y/s ")
if check == "y":
print "Welcome back, " + username + "!"
if check == "n":
print "I's sorry."
username = get_new_username()
print "We'll remember you when you come back, " + username + "!"
else:
username = get_new_username()
print "We'll remember you when you come back, " + username + "!"
greet_user()
Are you Ada ? y/s n I'm sorry. What is your name ? Eric We'll remember you when you come back, Eric!