华为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.mzph.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 …