Python內置經常使用模塊

  1. time和datatime
  2. Range
  3. os
  4. sys
  5. hashlib
  6. XML
  7. json & picle

一、time和datetime

time和datetime都是python處理時間和日期的內置模塊。html

1.1 time模塊

time模塊中時間表現的方式主要有三種:node

  一、timestamp:時間戳,時間戳表示的是從1970年1月1日00:00:00開始按秒計算的偏移量。python

  二、struct_time:時間元組,共有九個元素組。web

  三、format time :格式化時間,已格式化的結構使時間更具可讀性。包括自定義格式和固定格式。算法

 在python中直接獲取看下:shell

 import time
# 直接獲取timestamp
>>> time.time()
1560409102.4841187
# 直接獲取struct_time
>>> time.localtime()
time.struct_time(tm_year=2019, tm_mon=6, tm_mday=13, tm_hour=14, tm_min=59, tm_sec=0, tm_wday=3, tm_yday=164, tm_isdst=0)
# 直接獲取format time
>>> time.strftime('%Y-%m-%d %X')
'2019-06-13 15:01:35'

time模塊主要經過6種方法進行時間格式的轉換,看圖:編程

1.1.1 時間戳和時間元組轉換

>>> import time
>>> t1 = time.time()          # 獲取時間戳並賦值
>>> time.localtime(t1)        # 將時間戳轉換爲時間元組
time.struct_time(tm_year=2019, tm_mon=6, tm_mday=13, tm_hour=16, tm_min=25, tm_sec=14, tm_wday=3, tm_yday=164, tm_isdst=0)


>>> t2 = time.localtime()    # 獲取時間元組並賦值
>>> time.mktime(t2)          # 將時間元組轉換爲時間戳
1560414512.0

函數gmtime()的用法和localtime() 相似,localtime做用是格式化時間戳爲本地的時間,gmtime()做用是格式化時間戳爲格林尼治時間(世界標準時間UTC)。json

1.1.2. 格式化時間和時間元組轉換

 time.strftime() 函數接收以時間元組,並返回以可讀字符串表示的當地時間,格式由參數format決定;time.strptime() 函數接收以格式化時間,並返回時間元組,語法以下:windows

time.strftime(format,t1)瀏覽器

time.strptime(t2,format)

參數說明:

  • format — 格式字符串。
  • t1 — 可選的參數t是一個struct_time對象
  • t2 — 可選的參數t是一個format time對象
>>> import time
>>> time.strftime('%Y-%m-%d %X',time.localtime())
'2019-06-13 17:26:55'
>>> time.strptime('2019-05-01 14:10:15','%Y-%m-%d %X')
time.struct_time(tm_year=2019, tm_mon=5, tm_mday=1, tm_hour=14, tm_min=10, tm_sec=15, tm_wday=2, tm_yday=121, tm_isdst=-1)


# 時間元組中屬性及值
      屬性                            值
    tm_year(年)                  好比2017 
    tm_mon(月)                   1 - 12
    tm_mday(日)                  1 - 31
    tm_hour(時)                  0 - 23
    tm_min(分)                   0 - 59
    tm_sec(秒)                   0 - 61
    tm_wday(weekday)             0 - 6(0表示週日)
    tm_yday(一年中的第幾天)        1 - 366
    tm_isdst(是不是夏令時)        默認爲-1(1:是;0:否;-1:未知)


格式化時間中格式對應屬性
       %Y  年 Year with century as a decimal number.
    %m  月  Month as a decimal number [01,12].
    %d  日  Day of the month as a decimal number [01,31].
    %H  時  Hour (24-hour clock) as a decimal number [00,23].
    %M  分  Minute as a decimal number [00,59].
    %S  秒  Second as a decimal number [00,61].
    %z      Time zone offset from UTC.
    %a  周幾簡寫(英文Sun)    Locale's abbreviated weekday name.
    %A  周幾全名(英文Sunday)    Locale's full weekday name.
    %b  月份簡寫(英語Apr)    Locale's abbreviated month name.
    %B  月份全名(英語April)    Locale's full month name.
    %c      Locale's appropriate date and time representation.
    %I  十二小時制小時數   Hour (12-hour clock) as a decimal number [01,12].
    %p  AM/PM   Locale's equivalent of either AM or PM.
       %X   本地相應時間
    %x   本地相應日期

1.1.3. 還有2種轉換

由於格式化的時間字符串可讀性很高,因此有時須要將時間戳或時間元組轉換爲格式化時間:

 time.ctime() 函數把一個時間戳(按秒計算的浮點數)轉化爲格式化時間的形式。 若是參數未給或者爲None的時候,將會默認time.time()爲參數,

 time.asctime()若是參數未給或者爲None的時候,將會默認time.localtime()爲參數。

>>> import time
>>> time.ctime(1187640983)       # 傳入一個時間戳
'Tue Aug 21 04:16:23 2007'
>>> time.asctime()            # 默認time.localtime()爲參數
'Thu Jun 13 18:05:58 2019'
>>> time.asctime(time.localtime())
'Thu Jun 13 18:06:37 2019'

另外還有time.sleep()方法推遲調用程序的運行。

1.2 datetime模塊

datatime模塊從新封裝了time模塊,提供更多接口,提供的類有:date,time,datetime,timedelta,tzinfo。

這裏就只看一下datetime和timedelta類:

datetime.today():返回一個表示當前本地時間的datetime對象;
datetime.now([tz]):返回一個表示當前本地時間的datetime對象,若是提供了參數tz,則獲取tz參數所指時區的本地時間;
datetime.utcnow():返回一個當前utc時間的datetime對象;格林尼治時間
datetime.fromtimestamp(timestamp[, tz]):根據時間戮建立一個datetime對象,參數tz指定時區信息;
datetime.utcfromtimestamp(timestamp):根據時間戮建立一個datetime對象;格林尼治時間
datetime.combine(date, time):參數是datetime.datetime類的對象、datetime.date對象、datetime.time對象,獲得一個datetime.datetime對象;
datetime.strptime(date_string, format):將格式字符串轉換爲datetime對象;

方法和屬性

dt=datetime.now()#datetime對象
dt.year、month、day、hour、minute、second、microsecond、tzinfo:
dt.date():獲取date對象;
dt.time():獲取time對象;
dt. replace ([ year[ , month[ , day[ , hour[ , minute[ , second[ , microsecond[ , tzinfo] ] ] ] ] ] ] ]):
dt. timetuple ()
dt. utctimetuple ()
dt. toordinal ()
dt. weekday ()
dt. isocalendar ()
dt. isoformat ([ sep] )
dt. ctime ():返回一個日期時間的C格式字符串,等效於time.ctime(time.mktime(dt.timetuple()));
dt. strftime (format)

datetime加減

對日期和時間進行加減實際上就是把datetime日後或往前計算,獲得新的datetime。加減能夠直接用+-運算符,不過須要導入timedelta這個類:

>>> from datetime import datetime, timedelta
>>> now = datetime.now()
>>> now
datetime.datetime(2015, 5, 18, 16, 57, 3, 540997)
>>> now + timedelta(hours=10)
datetime.datetime(2015, 5, 19, 2, 57, 3, 540997)
>>> now - timedelta(days=1)
datetime.datetime(2015, 5, 17, 16, 57, 3, 540997)
>>> now + timedelta(days=2, hours=12)
datetime.datetime(2015, 5, 21, 4, 57, 3, 540997)
時區轉換

咱們能夠先經過utcnow()拿到當前的UTC時間,再轉換爲任意時區的時間:

# 拿到UTC時間,並強制設置時區爲UTC+0:00:
>>> utc_dt = datetime.utcnow().replace(tzinfo=timezone.utc)
>>> print(utc_dt)
2015-05-18 09:05:12.377316+00:00
# astimezone()將轉換時區爲北京時間:
>>> bj_dt = utc_dt.astimezone(timezone(timedelta(hours=8)))
>>> print(bj_dt)
2015-05-18 17:05:12.377316+08:00
# astimezone()將轉換時區爲東京時間:
>>> tokyo_dt = utc_dt.astimezone(timezone(timedelta(hours=9)))
>>> print(tokyo_dt)
2015-05-18 18:05:12.377316+09:00
# astimezone()將bj_dt轉換時區爲東京時間:
>>> tokyo_dt2 = bj_dt.astimezone(timezone(timedelta(hours=9)))
>>> print(tokyo_dt2)
2015-05-18 18:05:12.377316+09:00

時區轉換的關鍵在於,拿到一個datetime時,要獲知其正確的時區,而後強制設置時區,做爲基準時間。

利用帶時區的datetime經過astimezone()方法,能夠轉換到任意時區。

注:不是必須從UTC+0:00時區轉換到其餘時區,任何帶時區的datetime均可以正確轉換,例如上述bj_dt到tokyo_dt的轉換。

 二、random模塊

Python中的random模塊用於生成隨機數。下面介紹一下random模塊中最經常使用的幾個方法:

import random

1. random.random()       # 用於生成一個0到1的隨機浮點數:0<= n < 1.0
>>> random.random()
0.9646844371759081

2. random.uniform(a,b)    # 用於生成一個指定範圍內的隨機符點數n: a <= n <= b
>>> random.uniform(5,10)
6.584158762448463

3. random.randint(a,b)     # 用於生成一個指定範圍內的隨機整數n: a <= n <= b
>>> random.randint(4,10)
6

4. random.randrange([start],stop,step)    # 從指定範圍內,按指定基數遞增的集合中獲取一個隨機數
>>> random.randrange(10,18,3)
16

5. random.choice(sequence)      # 從序列sequence中獲取一個隨機元素
>>> random.choice('hello world')
'r'

6. random.shuffle()       # 用於將一個列表中的元素打亂,即將列表內的元素隨機排列
>>> p=[1,2,3,4,5,6,7]
>>> random.shuffle(p)
>>> p
[5, 1, 6, 7, 4, 3, 2]

7. random.sample(sequence,k)     # 從指定序列sequence中隨機獲取指定長度k的片段並隨機排列。注意:sample函數不會修改原有序列。
>>> L = ['A','B','C',1,2,3]
>>> random.sample(L,3)
[3, 'B', 1]
>>> L
['A', 'B', 'C', 1, 2, 3]

三、OS模塊

os模塊提供了多數操做系統的功能接口函數。當os模塊被導入後,它會自適應於不一樣的操做系統平臺,根據不一樣的平臺進行相應的操做,

在python編程時,常常和文件、目錄打交道,因此離不了os模塊。

os.getcwd()     獲取當前工做的目錄
os.chdir(path)    改變目錄到指定path目錄,注意windows標準路徑分隔符爲‘//’
os.makedirs('dirname1/dirname2')    可生成多層遞歸目錄
os.removedirs('dirname1')    若目錄爲空,則刪除,並遞歸到上一級目錄,如若也爲空,則刪除,依此類推
os.mkdir('dirname')    生成單級目錄
os.rmdir('dirname')    刪除單級空目錄,若目錄不爲空則沒法刪除,報錯
os.listdir('dirname')    列出指定目錄下的全部文件和子目錄,包括隱藏文件,並以列表方式打印
os.remove()  刪除一個文件
os.rename("oldname","newname")  重命名文件/目錄
os.stat('path/filename')  獲取文件/目錄信息
os.sep    輸出操做系統特定的路徑分隔符,win下爲"\\",Linux下爲"/"
os.linesep    輸出當前平臺使用的行終止符,win下爲"\t\n",Linux下爲"\n"
os.pathsep    輸出用於分割文件路徑的字符串
os.name    輸出字符串指示當前使用平臺。win->'nt'; Linux->'posix'
os.environ  獲取系統環境變量

os.path.abspath(path)  返回path規範化的絕對路徑
os.path.join(path1[, path2[, ...]])  將多個路徑組合後返回,第一個絕對路徑以前的參數將被忽略
os.path.split(path)  將path分割成目錄和文件名的二元組返回
os.path.splitext(path)  將path分割成目錄和文件擴展名的二元組返回
os.path.dirname(path)  返回path的目錄。其實就是os.path.split(path)的第一個元素
os.path.basename(path)  返回path最後的文件名。如何path以/或\結尾,那麼就會返回空值。即os.path.split(path)的第二個元素
os.path.exists(path)  若是path存在,返回True;若是path不存在,返回False
os.path.isabs(path)  若是path是絕對路徑,返回True
os.path.isfile(path)  若是path是一個存在的文件,返回True。不然返回False
os.path.isdir(path)  若是path是一個存在的目錄,則返回True。不然返回False
os.path.getatime(path)  返回path所指向的文件或者目錄的最後存取時間
os.path.getmtime(path)  返回path所指向的文件或者目錄的最後修改時間
os.path.getsize(filename)     獲取文件大小,目錄返回0

還有

os.system()   用於運行外部程序
    如web瀏覽器,在UNIX中,能夠這樣(找到瀏覽器位置)
    os.system('/usr/bin/firefox')
    在Windows中,能夠這樣(一樣,找到瀏覽器位置)
    os.system(r'C:\"Program Files (x86)"\"Mozilla Firefox"\firefox.exe')
    注意,這裏用引號將Program Files (x86)和Mozilla Firefox括起來了。若是不這樣作,底層的shell將受阻與空白處,並且這裏必須用反斜槓。

os.startfile()   Windows特有的函數,同system,並且略微比system好用
    os.system(r'C:\Program Files (x86)\Mozilla Firefox\firefox.exe')
    os.startfile接受一個普通路徑,即使有空白也沒有關係

實際操做後發現後者比前者好用(Windows),不光是空白緣由。
View Code

 四、sys模塊

sys.argv   命令行參數,包括腳本名
sys.exit([arg])    退出當前程序,可經過可選參數指定返回值或錯誤消息
sys.path    返回一個列表,包含模塊的搜索路徑,初始化時使用PYTHONPATH環境變量的值
sys.platform    返回操做系統平臺名稱
sys.version     獲取Python解釋程序的版本信息
sys.stdin       標準輸入流 —— 一個相似於文件的對象
sys.stdout     標準輸出流 —— 一個相似於文件的對象
sys.stderr      標準錯誤流 —— 一個相似於文件的對象

關於sys.argv

# 解釋爲:命令行參數,包括腳本(程序自己)名
# sys.argv[]說白了就是一個從程序外部獲取參數的橋樑,這個「外部」很關鍵,由於咱們從外部取得的參數能夠是多個,因此得到的是一個列表(list),
# 即sys.argv其實能夠看做是一個列表,因此才能用[]提取其中的元素。其第一個元素是程序自己,隨後才依次是外部給予的參數。
# 下面經過一個argv_test.py的例子看下:
# argv_test.py

import sys
a=sys.argv[0]
print(a)

# 而後命令行運行:python argv_test.py  獲得以下結果
argv_test.py
# 這就是‘0’指程序自己

# 而後將0改爲1,再運行一次,此次要加上一個參數:python argv_test.py hello  獲得:
hello

# 那咱們再把代碼修改一下:a=sys.argv[2:]
# 保存後,再運行程序,此次多加幾個參數,以空格隔開:python argv_test.py a b c d e f   獲得:
['b', 'c', 'd', 'e']


# sys.argv[ ]其實就是一個列表,裏邊的項爲用戶輸入的參數,關鍵就是要明白這參數是從程序外部輸入的,
# 而非代碼自己的什麼地方,要想看到它的效果就應該將程序保存了,從外部來運行程序並給出參數。
View Code

 五、hashlib模塊

Python的hashlib提供了常見的摘要算法,如MD5,SHA1等等。

什麼是摘要算法呢?摘要算法又稱哈希算法、散列算法。它經過一個函數,把任意長度的數據轉換爲一個長度固定的數據串(一般用

16進制的字符串表示)。

咱們以常見的摘要算法MD5爲例,計算出一個字符串的MD5值:

import hashlib

md5 = hashlib.md5()
md5.update('This is hashlib'.encode('utf-8'))
print(md5.hexdigest())

# 執行結果以下:
'4965310fcf57676786876118fd09912e'

若是內容較多能夠分屢次調用update,最後獲得的密文和一次性輸入是同樣的(注意空格)。

MD5是最多見的摘要算法,速度很快,生成結果是固定的128 bit字節,一般用一個32位的16進制字符串表示

另外一種常見的摘要算法是SHA1,調用SHA1和調用MD5徹底相似:

import hashlib
sh =  hashlib.sha1()
sh.update('This is '.encode('utf-8'))
sh.update('hashlib'.encode('utf-8'))
sh.hexdigest()

# 執行結果以下:
'cb61e3638d1cffe5c3080f358a33cb526ca7458c'

比SHA1更安全的算法是SHA256和SHA512,不過越安全的算法不只越慢,並且摘要長度更長。

有沒有可能兩個不一樣的數據經過某個摘要算法獲得了相同的摘要?徹底有可能,由於任何摘要算法都是把無限多的數據集合映射到一

個有限的集合中。這種狀況稱爲碰撞,這種狀況可能出現,可是很是很是困難。

 六、XML處理模塊

首先關於xml不作介紹,想了解能夠自行搜索或者去菜鳥驛站瞭解一下,並且也有該模塊的教程。

常見的 XML 編程接口有 DOM 和 SAX,這兩種接口處理 XML 文件的方式不一樣,固然使用場合也不一樣。

Python 有三種方法解析 XML,SAX,DOM,以及 ElementTree,簡單說下:

SAX:用事件驅動模型,經過觸發事件和回調函數來處理XML文件,是流式讀取XML文件,比較快,佔用內存少,但須要用戶實現回調。

DOM:將 XML 數據在內存中解析成一個樹,經過對樹的操做來操做XML,DOM功能齊全,可是比較笨重,一是比較慢,二是比較耗內存。

ElementTree:就像一個輕量級的DOM,具備方便友好的API。代碼可用性好,速度快,消耗內存少。

這裏就只簡單討論一下ElementTree解析方式

6.1 API名稱

from xml.etree import ElementTree as ET

6.2 基本概念

<country name="Liechtenstein">
    <rank>1</rank>
    <year>2008</year>
    <gdppc>141100</gdppc>
    <neighbor name="Austria" direction="E"/>
    <neighbor name="Switzerland" direction="W"/>
</country>
咱們把<country>xxx</contry>這種結構稱爲一個element,country稱做element的tag,<></>之間的內容稱做element的text或data,<>中的name稱做element的attrib,而整個XML樹被稱做ElementTree。
element是一個名爲xml.etree.ElementTree.Element的類,其描述爲:
class xml.etree.ElementTree.Element(tag, attrib={}, **extra)
此類的全部屬性和方法查看:
https://docs.python.org/2/library/xml.etree.elementtree.html   #element-objects

6.3 方法釋義

讀取xml數據

--讀取XML文件
import xml.etree.ElementTree as ET
tree = ET.parse('country_data.xml')
root = tree.getroot()
--讀取XML字符串
root = ET.fromstring(country_data_as_string)
--獲取element object的四大屬性tag、text、attrib以及tail
 root.tag #root element的tag
 root.text #root element的text
 root.attrib #root element自己的attrib,dict格式的
 root.tail #root element的tag結束到下一個tag之間的text
 --經過DICT邏輯獲取樹形結構的text,表示第一個child的第二個child element的text
 root[0][1].text

element object的方法

Element.iter(tag) --遍歷當前element樹全部子節點的element(不管是子節點仍是子節點的子節點),找到符合指定tag名的全部element,若是tag爲空則遍歷當前element樹,返回全部節點element(包含當前父節點)。2.7和3.2以前的版本無此方法,能夠用getiterator()代替。
Element.findall(tag) --遍歷當前節點的直接子節點,找到符合指定tag名的element,返回由element組成的list
Element.find(tag) --遍歷當前節點的直接子節點,找到符合指定tag名的第一個element
Element.get(key) --在當前element中獲取符合指定attrib名的value
...其餘方法參考官網

修改XML內容

ElementTree.write(file, encoding="us-ascii", xml_declaration=None, default_namespace=None, method="xml")  --將以前的修改寫入XML
Element.set(key,value) --設置element attrib
Element.append(subelement) --新增一個子element,extends(subelements)是3.2的新增用法,輸入參數必須是一個element序列
Element.remove(subelement) --刪除指定tag的element
示例:
>>> for rank in root.iter('rank'):
...     new_rank = int(rank.text) + 1
...     rank.text = str(new_rank)
...     rank.set('updated', 'yes')
...
>>> tree.write('output.xml')

6.4 實例

xml的格式以下,就是經過<>節點來區別數據結構的(country_data.xml)

<?xml version="1.0"?>
<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Austria" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N"/>
    </country>
    <country name="Panama">
        <rank updated="yes">69</rank>
        <year>2011</year>
        <gdppc>13600</gdppc>
        <neighbor name="Costa Rica" direction="W"/>
        <neighbor name="Colombia" direction="E"/>
    </country>
</data>

操做xml

import xml.etree.ElementTree as ET
 
tree = ET.parse("xmltest.xml")
root = tree.getroot()
print(root.tag)
 
#遍歷xml文檔
for child in root:
    print(child.tag, child.attrib)
    for i in child:
        print(i.tag,i.text)
 
#只遍歷year 節點
for node in root.iter('year'):
    print(node.tag,node.text)

刪除、修改xml內容

import xml.etree.ElementTree as ET
 
tree = ET.parse("xmltest.xml")
root = tree.getroot()
 
#修改
for node in root.iter('year'):
    new_year = int(node.text) + 1
    node.text = str(new_year)
    node.set("updated","yes")
 
tree.write("xmltest.xml")
 
 
#刪除node
for country in root.findall('country'):
   rank = int(country.find('rank').text)
   if rank > 50:
     root.remove(country)
 
tree.write('output.xml')

本身建立xml文檔

import xml.etree.ElementTree as ET
 
new_xml = ET.Element("namelist")
name = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"})
age = ET.SubElement(name,"age",attrib={"checked":"no"})
sex = ET.SubElement(name,"sex")
sex.text = '33'
name2 = ET.SubElement(new_xml,"name",attrib={"enrolled":"no"})
age = ET.SubElement(name2,"age")
age.text = '19'
 
et = ET.ElementTree(new_xml) #生成文檔對象
et.write("test.xml", encoding="utf-8",xml_declaration=True)
 
ET.dump(new_xml) #打印生成的格式

七、json&pickle模塊

經過將對象序列化能夠將其存儲在變量或者文件中,能夠保存當時對象的狀態,而且須要時能夠經過反序列化再次將這個對象讀取出來。

python中用於序列化的主要有兩個模塊

  • json,若是咱們要在不一樣的編程語言之間傳遞對象,就必須把對象序列化爲標準格式,好比XML,但更好的方法是序列化爲JSON,由於JSON表示出來就是一個字符串,能夠被全部語言讀取,也能夠方便地存儲到磁盤或者經過網絡傳輸。JSON不只是標準格式,而且比XML更快,並且能夠直接在Web頁面中讀取,很是方便。
  • pickle,用於python特有的類型和python的數據類型間進行轉換,而且可能不一樣版本的Python彼此都不兼容,所以,只能用Pickle保存那些不重要的數據。

Json模塊提供了四個功能:dumps和dump(序列化)、loads和load(反序列化)

pickle模塊提供了四個功能:dumps、dump、loads、load

>>> import pickle

# pickle.dumps()方法把任意對象序列化成一個bytes
>>> data = dict(name='Eric',age=23,score=59)
>>> d = pickle.dumps(data)
>>> d
b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x04\x00\x00\x00Ericq\x02X\x03\x00\x00\x00ageq\x03K\x17X\x05\x00\x00\x00scoreq\x04K;u.'

# pickle.dump()直接把對象序列化後寫入一個文件
>>> f = open('info.txt','wb')
>>> pickle.dump(data,f)
>>> f.close()

# pickle.loads()方法能夠把bytes反序列化
>>> pickle.loads(d)
{'name': 'Eric', 'age': 23, 'score': 59}

# pickle.load()方法從一個文件中直接反序列化出對象
>>> f = open('info.txt','rb')
>>> data_1=pickle.load(f)
>>> data_1
{'name': 'Eric', 'age': 23, 'score': 59}

json進階

JSON表示的對象就是標準的JavaScript語言的對象,JSON和Python內置的數據類型對應以下:

JSON類型 Python類型
{} dict
[] list
"string" str
1234.56 int或float
true/false True/False
null None

Python的dict對象能夠直接序列化爲JSON的{},不過,不少時候,你們更喜歡用class表示對象,好比定義Students類,而後序列化:

import json

class Student(object):
    def __init__(self, name, age, score):
        self.name = name
        self.age = age
        self.score = score

s = Student('Eric', 20, 59)
print(json.dumps(s))

# 執行結果以下:
Traceback (most recent call last):
  ...
TypeError:Object of type Student is not JSON serializable

錯誤的緣由是Student對象不是一個可序列化爲JSON的對象

仔細看看dump()方法的參數列表,能夠發現,除了第一個必須的obj參數外,dump()方法還提供了一大堆的可選參數:

https://docs.python.org/3/library/json.html#json.dumps

可選參數default就是把任意一個對象變成一個可序列爲JSON的對象,這裏須要把class轉換成dict:

print(json.dumps(s, default=lambda obj: obj.__dict__))

由於一般class的實例都有一個__dict__屬性,它就是一個dict,用來存儲實例變量。

一樣的道理,若是咱們要把JSON反序列化爲一個Student對象實例,load()方法首先轉換出一個dict對象,而後,咱們傳入的object_hook函數把dict實例Student實例:

def dict2student(d):
    return Student(d['name'], d['age'], d['score'])

即有:

s = Student('Eric', 20, 59)

#序列化
f = open('class_pickle.txt', 'w')       
json.dump(s, f, default=lambda obj: obj.__dict__)
f.close()

# 反序列化
def dict2studend(d):
    return Student(d['name'], d['age'], d['score'])


f = open('class_pickle.txt', 'r')
d = json.load(f, object_hook=dict2studend)
f.close()
print(d)
相關文章
相關標籤/搜索