華為python有必要學嗎_【華為云技術分享】這個 Python 庫有必要好好學學

這里看一個最基本的例子,這里給到一個 User 的 Class 定義,再給到一個 data 數據,像這樣:

1 class User(object):2 def __init__(self, name, age):3 self.name =name4 self.age =age5

6 data =[{7 'name': 'Germey',8 'age': 23

9 }, {10 'name': 'Mike',11 'age': 20

12 }]

現在我要把這個 data 快速轉成 User 組成的數組,變成這樣:

[User(name='Germey', age=23), User(name='Mike', age=20)]

你會怎么來實現?

或者我有了上面的列表內容,想要轉成一個 JSON 字符串,變成這樣:

[{"name": "Germey", "age": 23}, {"name": "Mike", "age": 20}]

你又會怎么操作呢?

另外如果 JSON 數據里面有各種各樣的臟數據,你需要在初始化時驗證這些字段是否合法,另外 User 這個對象里面 name、age 的數據類型不同,如何針對不同的數據類型進行針對性的類型轉換,這個你有更好的實現方案嗎?

初步思路

之前我寫過一篇文章這可能是 Python 面向對象編程的最佳實踐,介紹過 attrs 和 cattrs 這兩個庫,它們二者的組合可以非常方便地實現對象的序列化和反序列化。

譬如這樣:

1 fromattr import attrs, attrib2 fromcattr import structure, unstructure3

4 @attrs5 class User(object):6 name =attrib()7 age =attrib()8

9 data ={10 'name': 'Germey',11 'age': 23

12 }13 user =structure(data, User)14 print('user', user)15 json =unstructure(user)16 print('json', json)

運行結果:

1 user User(name='Germey', age=23)2 json {'name': 'Germey', 'age': 23}

好,這里我們通過 attrs 和 cattrs 這兩個庫來實現了單個對象的轉換。

首先我們要肯定一下 attrs 這個庫,它可以極大地簡化 Python 類的定義,同時每個字段可以定義多種數據類型。

但 cattrs 這個庫就相對弱一些了,如果把 data 換成數組,用 cattrs 還是不怎么好轉換的,另外它的 structure 和 unstructure 在某些情景下容錯能力較差,所以對于上面的需求,用這兩個庫搭配起來并不是一個最優的解決方案。

另外數據的校驗也是一個問題,attrs 雖然提供了 validator 的參數,但對于多種類型的數據處理的支持并沒有那么強大。

所以,我們想要尋求一個更優的解決方案。

更優雅的方案

這里推薦一個庫,叫做 marshmallow,它是專門用來支持 Python 對象和原生數據相互轉換的庫,如實現 object -> dict,objects -> list, string -> dict, string -> list 等的轉換功能,另外它還提供了非常豐富的數據類型轉換和校驗 API,幫助我們快速實現數據的轉換。

要使用 marshmallow 這個庫,需要先安裝下:

pip3 install marshmallow

好了之后,我們在之前的基礎上定義一個 Schema,如下:

1 classUserSchema(Schema):2 name =fields.Str()3 age =fields.Integer()4

5 @post_load6 def make(self, data, **kwargs):7 return User(**data)

還是之前的數據:

1 data =[{2 'name': 'Germey',3 'age': 23

4 }, {5 'name': 'Mike',6 'age': 20

7 }]

這時候我們只需要調用 Schema 的 load 事件就好了:

1 schema =UserSchema()2 users = schema.load(data, many=True)3 print(users)

輸出結果如下:

[User(name='Germey', age=23), User(name='Mike', age=20)]

這樣,我們非常輕松地完成了 JSON 到 User List 的轉換。

有人說,如果是單個數據怎么辦呢,只需要把 load 方法的 many 參數去掉即可:

1 data ={2 'name': 'Germey',3 'age': 23

4 }5

6 schema =UserSchema()7 user =schema.load(data)8 print(user)

輸出結果:

User(name='Germey', age=23)

當然,這僅僅是一個反序列化操作,我們還可以正向進行序列化,以及使用各種各樣的驗證條件。

下面我們再來看看吧。

更方便的序列化

上面的例子我們實現了序列化操作,輸出了 users 為:

[User(name='Germey', age=23), User(name='Mike', age=20)]

有了這個數據,我們也能輕松實現序列化操作。

序列化操作,使用 dump 方法即可

1 result = schema.dump(users, many=True)2 print('result', result)

運行結果如下:

result [{'age': 23, 'name': 'Germey'}, {'age': 20, 'name': 'Mike'}]

由于是 List,所以 dump 方法需要加一個參數 many 為 True。

當然對于單個對象,直接使用 dump 同樣是可以的:

1 result =schema.dump(user)2 print('result', result)

運行結果如下:

result {'name': 'Germey', 'age': 23}

這樣的話,單個、多個對象的序列化也不再是難事。

經過上面的操作,我們完成了 object 到 dict 或 list 的轉換,即:

1 object dict2 objects list

驗證

當然,上面的功能其實并不足以讓你覺得 marshmallow 有多么了不起,其實就是一個對象到基本數據的轉換嘛。但肯定不止這些,marshmallow 還提供了更加強大啊功能,比如說驗證,Validation。

比如這里我們將 age 這個字段設置為 hello,它無法被轉換成數值類型,所以肯定會報錯,樣例如下:

1 data ={2 'name': 'Germey',3 'age': 'hello'

4 }5

6 frommarshmallow import ValidationError7 try:8 schema =UserSchema()9 user, errors =schema.load(data)10 print(user, errors)11 except ValidationError ase:12 print('e.message', e.messages)13 print('e.valid_data', e.valid_data)

這里如果加載報錯,我們可以直接拿到 Error 的 messages 和 valid_data 對象,它包含了錯誤的信息和正確的字段結果,運行結果如下:

1 e.message {'age': ['Not a valid integer.']}2 e.valid_data {'name': 'Germey'}

因此,比如我們想要開發一個功能,比如用戶注冊,表單信息就是提交過來的 data,我們只需要過一遍 Validation,就可以輕松得知哪些數據符合要求,哪些不符合要求,接著再進一步進行處理。

當然驗證功能肯定不止這一些,我們再來感受一下另一個示例:

1 frompprint import pprint2 frommarshmallow import Schema, fields, validate, ValidationError3

4 classUserSchema(Schema):5 name = fields.Str(validate=validate.Length(min=1))6 permission = fields.Str(validate=validate.OneOf(['read', 'write', 'admin']))7 age = fields.Int(validate=validate.Range(min=18, max=40))8

9

10 in_data = {'name': '', 'permission': 'invalid', 'age': 71}11 try:12 UserSchema().load(in_data)13 except ValidationError aserr:14 pprint(err.messages)

比如這里的 validate 字段,我們分別校驗了 name、permission、age 三個字段,校驗方式各不相同。

如 name 我們要判斷其最小值為 1,則使用了 Length 對象。permission 必須要是幾個字符串之一,這里又使用了 OneOf 對象,age 又必須是介于某個范圍之間,這里就使用了 Range 對象。

下面我們故意傳入一些錯誤的數據,看下運行結果:

1 {'age': ['Must be greater than or equal to 18 and less than or equal to 40.'],2 'name': ['Shorter than minimum length 1.'],3 'permission': ['Must be one of: read, write, admin.']}

可以看到,這里也返回了數據驗證的結果,對于不符合條件的字段,一一進行說明。

另外我們也可以自定義驗證方法:

1 frommarshmallow import Schema, fields, ValidationError2

3 def validate_quantity(n):4 if n < 0:5 raise ValidationError('Quantity must be greater than 0.')6 if n > 30:7 raise ValidationError('Quantity must not be greater than 30.')8

9 classItemSchema(Schema):10 quantity = fields.Integer(validate=validate_quantity)11

12 in_data = {'quantity': 31}13 try:14 result =ItemSchema().load(in_data)15 except ValidationError aserr:16 print(err.messages)

通過自定義方法,同樣可以實現更靈活的驗證,運行結果:

{'quantity': ['Quantity must not be greater than 30.']}

對于上面的例子,還有更優雅的寫法:

1 frommarshmallow import fields, Schema, validates, ValidationError2

3

4 classItemSchema(Schema):5 quantity =fields.Integer()6

7 @validates('quantity')8 def validate_quantity(self, value):9 if value < 0:10 raise ValidationError('Quantity must be greater than 0.')11 if value > 30:12 raise ValidationError('Quantity must not be greater than 30.')

通過定義方法并用 validates 修飾符,使得代碼的書寫更加簡潔。

必填字段

如果要想定義必填字段,只需要在 fields 里面加入 required 參數并設置為 True 即可,另外我們還可以自定義錯誤信息,使用 error_messages 即可,例如:

1 frompprint import pprint2 frommarshmallow import Schema, fields, ValidationError3

4 classUserSchema(Schema):5 name = fields.String(required=True)6 age = fields.Integer(required=True, error_messages={'required': 'Age is required.'})7 city =fields.String(8 required=True,9 error_messages={'required': {'message': 'City required', 'code': 400}},10 )11 email =fields.Email()12

13 try:14 result = UserSchema().load({'email': 'foo@bar.com'})15 except ValidationError aserr:16 pprint(err.messages)

默認字段

對于序列化和反序列化字段,marshmallow 還提供了默認值,而且區分得非常清楚!如 missing 則是在反序列化時自動填充的數據,default 則是在序列化時自動填充的數據。

例如:

1 frommarshmallow import Schema, fields2 import datetime asdt3 import uuid4

5 classUserSchema(Schema):6 id = fields.UUID(missing=uuid.uuid1)7 birthdate = fields.DateTime(default=dt.datetime(2017, 9, 29))8

9 print(UserSchema().load({}))10 print(UserSchema().dump({}))

這里我們都是定義的空數據,分別進行序列化和反序列化,運行結果如下:

1 {'id': UUID('06aa384a-570c-11ea-9869-a0999b0d6843')}2 {'birthdate': '2017-09-29T00:00:00'}

可以看到,在沒有真實值的情況下,序列化和反序列化都是用了默認值。

這個真的是解決了我之前在 cattrs 序列化和反序列化時候的痛點啊!

指定屬性名

在序列化時,Schema 對象會默認使用和自身定義相同的 fields 屬性名,當然也可以自定義,如:

1 classUserSchema(Schema):2 name =fields.String()3 email_addr = fields.String(attribute='email')4 date_created = fields.DateTime(attribute='created_at')5

6 user = User('Keith', email='keith@stones.com')7 ser =UserSchema()8 result, errors =ser.dump(user)9 pprint(result)

運行結果如下:

1 {'name': 'Keith',2 'email_addr': 'keith@stones.com',3 'date_created': '2014-08-17T14:58:57.600623+00:00'}

反序列化也是一樣,例如:

1 classUserSchema(Schema):2 name =fields.String()3 email = fields.Email(load_from='emailAddress')4

5 data ={6 'name': 'Mike',7 'emailAddress': 'foo@bar.com'

8 }9 s =UserSchema()10 result, errors = s.load(data)

運行結果如下:

1 {'name': u'Mike',2 'email': 'foo@bar.com'}

嵌套屬性

對于嵌套屬性,marshmallow 當然也不在話下,這也是讓我覺得 marshmallow 非常好用的地方,例如:

1 fromdatetime import date2 frommarshmallow import Schema, fields, pprint3

4 classArtistSchema(Schema):5 name =fields.Str()6

7 classAlbumSchema(Schema):8 title =fields.Str()9 release_date =fields.Date()10 artist =fields.Nested(ArtistSchema())11

12 bowie = dict(name='David Bowie')13 album = dict(artist=bowie, title='Hunky Dory', release_date=date(1971, 12, 17))14

15 schema =AlbumSchema()16 result =schema.dump(album)17 pprint(result, indent=2)

這樣我們就能充分利用好對象關聯外鍵來方便地實現很多關聯功能。

以上介紹的內容基本算在日常的使用中是夠用了,當然以上都是一些基本的示例,對于更多功能,可以參考 marchmallow 的官方文檔:https://marshmallow.readthedocs.io/en/stable/,強烈推薦大家用起來。

作者:華為云享專家崔慶才靜覓

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/533980.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/533980.shtml
英文地址,請注明出處:http://en.pswp.cn/news/533980.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python求平行四邊形面積_python 已知平行四邊形三個點,求第四個點的案例

我就廢話不多說了&#xff0c;大家還是直接看代碼吧&#xff01;import numpy as np#已知平行四邊形三個點&#xff0c;求第四個點#計算兩點之間的距離def CalcEuclideanDistance(point1,point2):vec1 np.array(point1)vec2 np.array(point2)distance np.linalg.norm(vec1 -…

eview面板數據之混合回歸模型_【視頻教程】Eviews系列25|面板數據回歸分析之Hausman檢驗及本章常見問題解答...

點擊上方關注我們!本期我們學習Eviews統計建模最后一部分--面板數據回歸分析Hausman檢驗及本章常見問題解答。實操&#xff1a;Hausman檢驗判斷是固定效應模型還是隨機效應模型上期我們講到模型判斷若選擇模型2,需進一步通過Hausman檢驗判斷固定效應還是隨機效應&#xff0c;接…

python打出由邊框包圍的_python opencv 圖像邊框(填充)添加及圖像混合的實現方法(末尾實現類似幻燈片漸變的效果)...

圖像邊框的實現圖像邊框設計的主要函數cv.copyMakeBorder()——實現邊框填充主要參數如下&#xff1a;參數一&#xff1a;源圖像——如&#xff1a;讀取的img參數二——參數五分別是&#xff1a;上下左右邊的寬度——單位&#xff1a;像素參數六&#xff1a;邊框類型&#xff1…

mysql5.7.21備份腳本_Shell腳本使用匯總整理——mysql數據庫5.7.8以后備份腳本

#!/bin/sh#db_backups_conf.txt文件路徑db_backups_conf"/wocloud/shell/db_backups_conf.txt"#判斷文件是否存在if [ -f "${db_backups_conf}" ];thenecho $(date %Y-%m-%d %H:%M:%S)" 數據庫配置信息文件存在&#xff0c;開始進行數據備份"#獲…

python嵌套列表操作_python基礎(list列表的操作,公共方法,列表嵌套,元祖)...

list 列表索引&#xff0c;切片與str相同。列表的操作(增刪改查)1&#xff0c;增加.append()  追加&#xff0c;增加到最后li [alex,wusir,egon,女神,taibai]li.append(ppp)print(li).insert()  中間插入&#xff0c;通過索引li [alex,wusir,egon,女神,taibai]li.insert(…

mybatis mysql selectkey_Mybatis示例之SelectKey的應用

SelectKey在Mybatis中是為了解決Insert數據時不支持主鍵自動生成的問題&#xff0c;他可以很隨意的設置生成主鍵的方式。不管SelectKey有多好&#xff0c;盡量不要遇到這種情況吧&#xff0c;畢竟很麻煩。SelectKey需要注意order屬性&#xff0c;像Mysql一類支持自動增長類型的…

python程序設計上機實踐第三章答案_20192419 實驗三《Python程序設計》實驗報告

學號 2019-2020-2 《Python程序設計》實驗3報告課程&#xff1a;《Python程序設計》班級&#xff1a;1924姓名&#xff1a; 萬騰陽學號&#xff1a;20192419實驗教師&#xff1a;王志強實驗日期&#xff1a;2020年5月16日必修/選修&#xff1a; 公選課1.實驗內容創建服務端和客…

完成數獨的算法 python_python實現數獨算法實例

本文實例講述了python實現數獨算法的方法。分享給大家供大家參考。具體如下&#xff1a;# -*- coding: utf-8 -*-Created on 2012-10-5author: Administratorfrom collections import defaultdictimport itertoolsa [[ 0, 7, 0, 0, 0, 0, 0, 0, 0], #0[ 5, 0, 3, 0, 0, 6, 0, …

python讀取多個文件csv_Python:讀取多個文本文件并寫入相應的csv文件

我在別處找不到這個問題的答案&#xff0c;所以我將繼續把它貼在這里&#xff1a;我有一個Python腳本&#xff0c;它將讀取文本文件的內容&#xff0c;將其內容拆分為單詞&#xff0c;然后輸出一個CSV文件&#xff0c;該文件將文本縮減為單詞頻率列表。(最后&#xff0c;我將插…

java treetable_在Swing中創建TreeTable | 學步園

TreeTable是Tree和Table的一個結合&#xff0d;就是一個即能夠展開和收起行&#xff0c;同時也能夠顯示多個列的組件。在Swing的標準包里沒有一個叫做JtreeTable的組件&#xff0c;但是我們很容易通過把Jtree做成Jtable的渲染器來創建一個這樣的組件。這篇文章就是關于如何使用…

python爬去微博十大流行語_用python重新定義【2019十大網絡流行語】-后臺/架構/數據庫-敏捷大拇指-一個敢保留真話的IT精英社區...

↑關注 置頂 ~ 有趣的不像個技術號52568040f9313098ffa367d9d9d21437.jpg (5.73 KB, 下載次數: 0)2019-12-10 04:43 上傳3f4d5fe0016d011a7a68af763314befd.jpg (1.06 KB, 下載次數: 0)2019-12-10 04:43 上傳“文明互鑒真硬核&#xff0c;融梗檸檬誰覺得。霸凌第一九九六&…

java中怎么獲取配置文件的值_java如何獲取配置文件的值

轉&#xff1a;原創 編碼小王子 發布于2018-10-11 18:07:52 閱讀數 2722 收藏展開java大型項目中都會很多系統常量,比如說數據庫的賬號和密碼,以及各種token值等,都需要統一的管理,如果零落的散布到各個類等具體的代碼中的話,在后期管理上將是一場災難,所有需要對這些變量進行統…

python實現隊列_用Python實現的數據結構與算法:隊列

一、概述隊列(Queue)是一種先進先出(FIFO)的線性數據結構&#xff0c;插入操作在隊尾(rear)進行&#xff0c;刪除操作在隊首(front)進行。二、ADT隊列ADT(抽象數據類型)一般提供以下接口&#xff1a;Queue() 創建隊列enqueue(item) 向隊尾插入項dequeue() 返回隊首的項&#xf…

java 監聽窗口是否改變_JAVA項目監聽文件是否發生變化

一.spring容器都初始化完成之后做操作packagecom.bijian.study.listener;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.context.ApplicationListener;importorg.springframework.context.event.ContextRefreshedEvent;importorg.s…

笨辦法學python3 pdf 腳本之家_解決python3輸入的坑——input()

如下所示&#xff1a;a,b,c,d input()很簡單的代碼&#xff0c;如果輸入為1 -1 -2 3結果會報錯&#xff0c;原因在于input函數會將你的輸入作為python腳本運行&#xff0c;那么輸入就變成了1-1 -2 3&#xff0c;即0 -2 3結果當然是錯誤的了&#xff0c;解決辦法就是將輸入用引…

java 數組寫法_java書寫、數據類型、數組定義

這里只記錄java與php、javascript不同的地方&#xff0c;相同的地方就不贅述了。1.java文件源碼為以.java為后綴的文件&#xff0c;字節碼文件是以.class為后綴的文件。2.寫好一個java源碼之后&#xff0c;cmd進入源碼文件盤符&#xff0c;用命令 javac helloworld.java將源碼轉…

python爬蟲高級知識點_Python爬蟲知識點梳理總結,殿堂級小白入門必讀

數據分析是任何技術一樣。你應該學習的目標。目標就像燈塔,指引你前進。我見過很多合作伙伴學習學習,然后學會放棄。事實上,很大一部分原因是沒有明確的目標,所以你必須清楚學習的目的。你準備學習爬行之前,問問你自己為什么你想學爬行。有些人為了工作,一些為了好玩,和做一定黑…

java running_Running

/****/package test;import java.sql.ResultSet;import java.sql.SQLException;/*** author huangqin**/public class QuestString {private int curPage;//當前頁數private int maxPage;//最大頁數private int maxRowCount;//總記錄數private int pageSize2;//每頁顯示的記錄數…

python停用詞表_多版本中文停用詞詞表 + 多版本英文停用詞詞表 + python詞表合并程序...

文章簡介與更新記錄如果你只想獲取中文停用詞此表,請直接到文章結尾下載項目文件,其中包括三個中文停用詞詞表,一個英文停用詞詞表和一個合并詞表的.py文件2017/07/04 創建文章,上傳文件2017/07/04 更新了合并代碼,添加了新的中文停用詞表(哈工大擴展版本)和一個新的停用詞表,現…

mysql collect_set_hive列轉行 (collect_set())

一、問題hive如何將a b 1a b 2a b 3c d 4c d 5c d 6變為&#xff1a;a b 1,2,3c d 4,5,6二、數據test.txta b 1a b 2a b 3c d …