python中利用少量代码快速实现从类对象中抽取所需属性的一种实践

项目中有可能会碰到这样一种场景:

根据一个id,查询得到和id对应的完整数据信息存储对象,比如书籍id到书籍详细信息,用户id到用户详细信息等,详细信息字段可能包括几十甚至上百个数据字段,真正需要返回给调用方的字段实际上却只占其中一小部分,这是出于性能和带宽的考虑(甚至在有些场景中,处于隐私或者安全考虑,强制要求不能返回非协议定义的信息字段,比如第三方登录一般只返回用户昵称、性别等少量信息),一般会从详细的数据对象中抽取出所需要的信息组装一个新的简化对象。

今天碰到这样一个问题,需要将一个存储多个详细信息对象的list转化为一个简化对象的list返回给主调方,尝试了数种方法后,通过使用列表推导、字典推导以及getattr内置函数这三者,用数行代码即达到了这一目的,

原始数据结构定义:

class detail_info(object):
    def __init(self):
        self.id = ‘‘
        self.title = ‘‘
        self.name = ‘‘
        self.url = ‘‘
        self.avatar = ‘‘
        self.p1 = None
        self.p2 = None
        self.p3 = None
        self.p4 = None
        self.p5 = None
        self.p6 = None
        self.p7 = None
        self.p8 = None
        ...

实际所需要返回的信息字段为id,title,url和p1,放入一个字典即可,如下为针对一个长度为5的list执行的结果,经过字典推导+列表推导,并通过getattr动态获取类的属性值,两行代码即实现了将所需字段抽取出来形成一个以dict为元素的list。

>>> needed_keys = [‘id‘, ‘title‘, ‘url‘, ‘p1‘]
>>> [{k: getattr(x, k) for k in needed_keys} for x in alist]
[{‘url‘: ‘url_0‘, ‘p1‘: ‘p1_0‘, ‘id‘: ‘id_0‘, ‘title‘: ‘title_0‘}, {‘url‘: ‘url_1‘, ‘p1‘: ‘p1_1‘, ‘id‘: ‘id_1‘, ‘title‘: ‘title_1‘}, {‘url‘: ‘url_2‘, ‘p1‘: ‘p1_2‘, ‘id‘: ‘id_2‘, ‘title‘: ‘title_2‘}, {‘url‘: ‘url_3‘, ‘p1‘: ‘p1_3‘, ‘id‘: ‘id_3‘, ‘title‘: ‘title_3‘}, {‘url‘: ‘url_4‘, ‘p1‘: ‘p1_4‘, ‘id‘: ‘id_4‘, ‘title‘: ‘title_4‘}, {‘url‘: ‘url_5‘, ‘p1‘: ‘p1_5‘, ‘id‘: ‘id_5‘, ‘title‘: ‘title_5‘}]

如果要直接返回一个类似如下的简化结构:

class SimpleInfo(object):
    def __init__(self):
        self.id = ‘‘
        self.title = ‘‘
        self.url = ‘‘
        self.p1 = None

也只需要预先定义一个和alist等长的存储SimpleInfo结构的等长blist,组合zip函数的使用,稍加改动即可:

>>> blist = [SimpleInfo() for i in range(0, len(alist))]
>>> needed_keys = [‘id‘, ‘title‘, ‘url‘, ‘p1‘]
>>> [[setattr(y, k, getattr(x, k)) for k in needed_keys] for x, y in zip(alist,blist)]
[[None, None, None, None], [None, None, None, None], [None, None, None, None], [None, None, None, None], [None, None, None, None]]

 >>> blist[0].__dict__
 {‘url‘: ‘url_0‘, ‘p1‘: ‘p1_0‘, ‘id‘: ‘id_0‘, ‘title‘: ‘title_0‘}

这里列表推导的代码使用setattr对blist中的SimpleInfo对象属性赋值,由于函数返回值为None,所以列表推导的结果是一个元素为None的list,通过查看blist[0]的信息,可以确认实际要赋值的属性已经通过setattr赋值给blist中对应的对象了。

时间: 2024-10-13 22:01:09

python中利用少量代码快速实现从类对象中抽取所需属性的一种实践的相关文章

SpingMVC中利用BindingResult将错误信息返回到页面中

SpingMVC中利用BindingResult将错误信息返回到页面中. ActionFrom中: private String name; private String password; get()/set()....... JSP中: <form:form id="T51000ActionForm" name="T51000ActionForm" modelAttribute="t51000ActionForm"  method=&q

Myeclipse中把java代码导成UML类图

1.右键点击项目名称,选择New-------àUML2 Model 2.给类图命名 3.导成类图 1)如果要把整个项目导成类图,则把整个项目拖到类图中 2)如果要把单个类导成类图,则把单个java类拖到类图中 4.右键点击类图,选择Export All Diagrms 5.点击Browse选择导成的类图的路径,选择导出的图片的格式,点击finish,生成图片.

实例化类对象中alloc和inti的区别

在OC中,实例化一个类对象需要通过调用alloc和init两个系统既定方法进行初始化,比如: Fraction *frac=[[Fraction alloc]init]; 两者的区别如下: 1.alloc方法保证对象所对应的类里定义的所有实例变量都变成初始状态,但并没有使该对象本身进行初始化: 2.init方法用于初始化类要实例化的对象,它可以返回一个值,即被初始化的对象. ps:当然实例化一个对象还可以采用一种简便的方式,比如: Fractiion *frac=[Fraction new];

Android中利用icodetools工具快速定位App破解中关键点方法

icodetools工具地址:https://github.com/fourbrother/icodetools 一.前言 在前面已经介绍了icodetools工具的实现原理和具体使用规则,关于这部分的知识点还不了解的同学可以去下面两篇文章详细查看:Android中注入代码工具icodetools原理篇,Android中注入代码工具icodetools完善篇.同时这个工具已经放到github上了,感兴趣的同学可以下载尝试各种app的代码注入功能. 那么有了这两篇文章之后,现在我得实际操作了,要动

Asp.net中利用NPOI组件快速导入导出Execl数据

相信很多童鞋都开发过Execl的导入导出功能,最近产品中无论是后台数据分析的需要,还是前端满足用户管理的方便,都有Execl导入导出的维护需求产生. 以前做这个功能,如果是web,利用HttpContext.Current.Response.ContentType ="application/ms-excel";就可以导出html数据表格到execl中,这种方法的问题就是编码格式的兼容性太差,用Mac OS之类的 office打开直接乱码给你看.或者是调用office的COM组件,或宏

MySQL中利用RENAME TABLE快速高效重命名库(schema)

目前的MySQL中一旦创建的了新的库(schema)就无法对它进行重命名,所以如果需要对一个库重命名一般的做法是把目标库中的数据dump出来后导入想重命名的新库中,在MySQL的导入中是使用大量的insert,大量使用了DML,如果是大数据量的库那就很低效,其实在MySQL中可以利用RENAME TABLE这种DDL的方式来移动表数据后来重命名库,下面就简单的介绍一下.首先,RENAME TABLE使用方法很简单: RENAME TABLE old_table TO new_table; 由此在

利用JS代码快速获得知网论文作为参考文献的引用文本

写论文的时候,发现知网虽然提供了生成参考文献引用标注的功能,但是效率仍然不太高.我就忙里偷闲写了一段简单的脚本,能无延迟地生成这段引用文本.目前支持期刊论文和硕士论文. 代码: (function(){var a=[],b,c,t,w,i='.sourinfo',z=i+'>p a',f=function(e){return $(e).html()};$('.author a').each(function(i,e){a.push(f(e))});b=f(i+'>.title a');if(b

java 利用反射获取类对象中List的值

Field[] fields = Object.getClass().getDeclaredFields();//Object是已经被赋值的对象实例 for (Field field : fields) {if (!field.isAccessible()) { field.setAccessible(true); } if (List.class.isAssignableFrom(field.getType())) { Type t = field.getGenericType(); if (

java中的反射,知道类名创建类,还可以设置私有属性的值

刚刚学到了反射,感觉反射的功能好强大,所以想写篇博客记录下自己的学习成果. 利用反射来创建对象. Class c1=Class.forName("test.Person");//通过类名来创建类,这里test.person只是一个类名,.这个person类代码在//本文最下方 /** *情况1:调用无参的构造方法来创建对象 */ Person p=c1.newInstance();//这样就创建好了 /** *情况2:调用有参构造方法 */ Constructor cs=c1.getC