#! /usr/bin/env python
-*- coding:utf-8 -*-
'''
@Author:gcan
@Email:1528667112@qq.com
@Site:http://www.gcan.top
@File:json_data.py
@Software:PyCharm
@Date:2018-05-15 23:08:46
@Version:1.0.0
'''
存儲數(shù)據(jù)
很多程序都要求用戶輸入某種信息,如讓用戶存儲游戲首選項或提供要可視化的數(shù)據(jù)蛙粘。不管專注的是什么朽色,程序都把用戶提供的信息存儲在列表和字典等數(shù)據(jù)結(jié)構(gòu)中。用戶關閉
程序時组题,你幾乎總是要保存他們提供的信息;一種簡單的方式是使用模塊json 來存儲數(shù)據(jù)葫男。
模塊json 讓你能夠?qū)⒑唵蔚腜ython數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)儲到文件中,并在程序再次運行時加載該文件中的數(shù)據(jù)崔列。你還可以使用json 在Python程序之間分享數(shù)據(jù)梢褐。更重要的是旺遮,JSON數(shù)據(jù)
格式并非Python專用的,這讓你能夠?qū)⒁訨SON格式存儲的數(shù)據(jù)與使用其他編程語言的人分享盈咳。這是一種輕便格式耿眉,很有用,也易于學習鱼响。 注意 JSON(JavaScript Object Notation)格式最初是為JavaScript開發(fā)的鸣剪,但隨后成了一種常見格式,被包括Python在內(nèi)的眾多語言采用丈积。
使用json.dump() 和json.load()
我們來編寫一個存儲一組數(shù)字的簡短程序筐骇,再編寫一個將這些數(shù)字讀取到內(nèi)存中的程序。第一個程序?qū)⑹褂胘son.dump() 來存儲這組數(shù)字江滨,而第二個程序?qū)⑹?br>
用json.load() 铛纬。
函數(shù)json.dump() 接受兩個實參:要存儲的數(shù)據(jù)以及可用于存儲數(shù)據(jù)的文件對象。下面演示了如何使用json.dump() 來存儲數(shù)字列表:
import json
numbers = [2, 3, 5, 7, 11, 13]
filename = 'numbers.json'
with open(filename, 'w') as f_obj:
json.dump(numbers, f_obj)
我們先導入模塊json 唬滑,再創(chuàng)建一個數(shù)字列表告唆。我們指定了要將該數(shù)字列表存儲到其中的文件的名稱。通常使用文件擴展名.json來指出文件存儲的數(shù)據(jù)為JSON格式晶密。
接下來擒悬,我們以寫入模式打開這個文件,讓json 能夠?qū)?shù)據(jù)寫入其中稻艰。我們使用函數(shù)json.dump() 將數(shù)字列表存儲到文件numbers.json中懂牧。
這個程序沒有輸出,但我們可以打開文件numbers.json连锯,看看其內(nèi)容归苍。數(shù)據(jù)的存儲格式與Python中一樣: [2, 3, 5, 7, 11, 13]
下面再編寫一個程序用狱,使用json.load() 將這個列表讀取到內(nèi)存中:
import json
filename = 'numbers.json'
with open(filename) as f_obj:
numbers = json.load(f_obj)
print(numbers)
我們確保讀取的是前面寫入的文件运怖。這次我們以讀取方式打開這個文件,因為Python只需讀取這個文件夏伊。我們使用函數(shù)json.load() 加載存儲在 numbers.json中的信息摇展,并將其存儲到變量numbers 中。
最后溺忧,我們打印恢復的數(shù)字列表咏连,看看它是否與number_writer.py中創(chuàng)建的數(shù)字列表相同: [2, 3, 5, 7, 11, 13]
保存和讀取用戶生成的數(shù)據(jù)
對于用戶生成的數(shù)據(jù),使用json 保存它們大有裨益鲁森,因為如果不以某種方式進行存儲祟滴,等程序停止運行時用戶的信息將丟失。
下面來看一個這樣的例子:用戶首次運行程序時 被提示輸入自己的名字歌溉,這樣再次運行程序時就記住他了垄懂。
我們先來存儲用戶的名字:
import json
username = input("What is your name? ")
filename = 'username.json'
with open(filename, 'w') as f_obj:
json.dump(username, f_obj)
print("We'll remember you when you come back, " + username + "!")
我們提示輸入用戶名骑晶,并將其存儲在一個變量中。接下來草慧,我們調(diào)用json.dump() 桶蛔,并將用戶名和一個文件對象傳遞給它,從而將用戶名存儲到文件中漫谷。然后仔雷,我們打印一條消息,指出我們存儲了他輸入的信息
現(xiàn)在再編寫一個程序舔示,向其名字被存儲的用戶發(fā)出問候:
import json
filename = 'username.json'
with open(filename) as f_obj:
username = json.load(f_obj)
print("Welcome back, " + username + "!")
我們使用json.load() 將存儲在username.json中的信息讀取到變量username 中碟婆。恢復用戶名后斩郎,我們就可以歡迎用戶回來了
我們需要將這兩個程序合并到一個程序(remember_me.py)中脑融。這個程序運行時,我們將嘗試從文件username.json中獲取用戶名缩宜,
因此我們首先編寫一個嘗試恢復用戶名的try 代 碼塊肘迎。如果這個文件不存在,我們就在except 代碼塊中提示用戶輸入用戶名锻煌,并將其存儲在username.json中妓布,以便程序再次運行時能夠獲取它
如果以前存儲了用戶名,就加載它
否則宋梧,就提示用戶輸入用戶名并存儲它
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 remember you when you come back, " + username + "!")
else:
print("Welcome back, " + username + "!")
這里沒有任何新代碼匣沼,只是將前兩個示例的代碼合并到了一個程序中。我們嘗試打開文件username.json捂龄。如果這個文件存在释涛,就將其中的用戶名讀取到內(nèi)存中,
再執(zhí)行else 代碼塊倦沧,即打印一條歡迎用戶回來的消息唇撬。用戶首次運行這個程序時,文件username.json不存在展融,將引發(fā)FileNotFoundError 異常窖认,因此Python將執(zhí) 行except 代碼塊:
提示用戶輸入其用戶名,再使用json.dump() 存儲該用戶名告希,并打印一句問候語扑浸。
無論執(zhí)行的是except 代碼塊還是else 代碼塊,都將顯示用戶名和合適的問候語燕偶。
重構(gòu)
你經(jīng)常會遇到這樣的情況:代碼能夠正確地運行喝噪,但可做進一步的改進——將代碼劃分為一系列完成具體工作的函數(shù)。這樣的過程被稱為重構(gòu) 指么。重構(gòu)讓代碼更清晰酝惧、更易于理解驰吓、更容易擴展。
要重構(gòu)系奉,可將其大部分邏輯放到一個或多個函數(shù)中檬贰。重點是問候用戶,因此我們將其所有代碼都放到一個名為greet_user() 的函數(shù)中:
import json
def greet_user():
"""問候用戶缺亮,并指出其名字"""
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 remember you when you come back, " + username + "!")
else:
print("Welcome back, " + username + "!")
greet_user()
考慮到現(xiàn)在使用了一個函數(shù)翁涤,我們刪除了注釋,轉(zhuǎn)而使用一個文檔字符串來指出程序是做什么的萌踱。這個程序更清晰些葵礼,但函數(shù)greet_user() 所做的不僅僅是問候用戶,還在存儲了用戶名時獲取它并鸵,而在沒有存儲用戶名時提示用戶輸入一個鸳粉。
下面來重構(gòu)greet_user() ,讓它不執(zhí)行這么多任務园担。為此届谈,我們首先將獲取存儲的用戶名的代碼移到另一個函數(shù)中:
import json
def get_stored_username():
"""如果存儲了用戶名,就獲取它"""
filename = 'username.json'
try:
with open(filename) as f_obj:
username = json.load(f_obj)
except FileNotFoundError:
return None
else:
return username
def greet_user():
"""問候用戶弯汰,并指出其名字"""
username = get_stored_username()
if username:
print("Welcome back, " + username + "!")
else:
username = input("What is your name? ")
filename = 'username.json'
with open(filename, 'w') as f_obj:
json.dump(username, f_obj)
print("We'll remember you when you come back, " + username + "!")
greet_user()
新增的函數(shù)get_stored_username() 目標明確艰山,文檔字符串指出了這一點。如果存儲了用戶名咏闪,這個函數(shù)就獲取并返回它;
如果文件username.json不存在曙搬,這個函數(shù) 就返回None。這是一種不錯的做法:函數(shù)要么返回預期的值鸽嫂,要么返回None ;這讓我們能夠使用函數(shù)的返回值做簡單測試纵装。
如果成功地獲取了用戶名,就打印一條歡迎用戶回來的消息据某,否則就提示用戶輸入用戶名橡娄。