在python的类中动态添加属性与生成对象


Posted in Python onSeptember 17, 2016

本文将通过一下几个方面来一一进行解决

      1、程序的主要功能

      2、实现过程

      3、类的定义

      4、用生成器generator动态更新每个对象并返回对象

      5、使用strip 去除不必要的字符

      6、rematch匹配字符串

      7、使用timestrptime提取字符串转化为时间对象

      8、完整代码

程序的主要功能

现在有个存储用户信息的像表格一样的文档:第一行是属性,各个属性用逗号(,)分隔,从第二行开始每行是各个属性对应的值,每行代表一个用户。如何实现读入这个文档,每行输出一个用户对象呢?
另外还有4个小要求:

每个文档都很大,如果一次性把所有行生成的那么多对象存成列表返回,内存会崩溃。程序中每次只能存一个行生成的对象。

用逗号隔开的每个字符串,前后可能有双引号(”)或者单引号('),例如”张三“,要把引号去掉;如果是数字,有+000000001.24这样的,要把前面的+和0都去掉,提取出1.24

文档中有时间,形式可能是2013-10-29,也可能是2013/10/29 2:23:56 这样的形式,要把这样的字符串转成时间类型

这样的文档有好多个,每个的属性都不一样,例如这个是用户的信息,那个是通话纪录。所以类中的具体属性有哪些要根据文档的第一行动态生成

实现过程

1.类的定义

由于属性是动态添加的,属性-值 对也是动态添加的,类中要含有updateAttributes()updatePairs()两个成员函数即可,此外用列表attributes存储属性,词典attrilist存储映射。其中init()函数为构造函数。 __attributes前有下划线表示私有变量,不能在外面直接调用。实例化时只需a=UserInfo()即可,无需任何参数。

class UserInfo(object):
 'Class to restore UserInformation'
 def __init__ (self):
  self.attrilist={}
  self.__attributes=[]
 def updateAttributes(self,attributes):
  self.__attributes=attributes
 def updatePairs(self,values):
  for i in range(len(values)):
   self.attrilist[self.__attributes[i]]=values[i]

2.用生成器(generator)动态更新每个对象并返回对象

生成器相当于一个只需要初始化一次,就可自动运行多次的函数,每次循环返回一个结果。不过函数用return 返回结果,而生成器用yield 返回结果。每次运行都在yield返回,下一次运行从yield之后开始。例如,我们实现斐波拉契数列,分别用函数和生成器实现:

def fib(max):
 n, a, b = 0, 0, 1
 while n < max:
  print(b)
  a, b = b, a + b
  n = n + 1
 return 'done'

我们计算数列的前6个数:

>>> fib(6)
1
1
2
3
5
8
'done'

如果用生成器的话,只要把 print 改成 yield 就可以了。如下:

def fib(max):
 n, a, b = 0, 0, 1
 while n < max:
  yield b
  a, b = b, a + b
  n = n + 1

使用方法:

>>> f = fib(6)
>>> f
<generator object fib at 0x104feaaa0>
>>> for i in f:
...  print(i)
... 
1
1
2
3
5
8
>>>

可以看到,生成器fib本身是个对象,每次执行到yield会中断返回一个结果,下次又继续从yield的下一行代码继续执行。生成器还可以用generator.next()执行。

在我的程序中,生成器部分代码如下:

def ObjectGenerator(maxlinenum):
 filename='/home/thinkit/Documents/usr_info/USER.csv'
 attributes=[]
 linenum=1
 a=UserInfo()
 file=open(filename)
 while linenum < maxlinenum:
  values=[]
  line=str.decode(file.readline(),'gb2312')#linecache.getline(filename, linenum,'gb2312')
  if line=='':
   print'reading fail! Please check filename!'
   break
  str_list=line.split(',')
  for item in str_list:
   item=item.strip()
   item=item.strip('\"')
   item=item.strip('\'')
   item=item.strip('+0*')
   item=catchTime(item)
   if linenum==1:
    attributes.append(item)
   else:
    values.append(item)
  if linenum==1:
   a.updateAttributes(attributes)
  else:
   a.updatePairs(values)
   yield a.attrilist #change to ' a ' to use
  linenum = linenum +1

其中,a=UserInfo()为类UserInfo的实例化.因为文档是gb2312编码的,上面使用了对应的解码方法。由于第一行是属性,有个函数将属性列表存入UserInfo中,即updateAttributes();后面的行则要将 属性-值 对读入一个字典中存储。p.s.python中的字典相当于映射(map).

3.使用strip 去除不必要的字符

从上面代码中,可以看到使用str.strip(somechar)即可去除str前后的somechar字符。somechar可以是符号,也可以是正则表达式,如上:

item=item.strip()#除去字符串前后的所有转义字符,如\t,\n等
item=item.strip('\"')#除去前后的"
item=item.strip('\'')
item=item.strip('+0*')#除去前后的+00...00,*表示0的个数可以任意多,也可以没有

4.re.match匹配字符串

函数语法:

re.match(pattern, string, flags=0)

函数参数说明:

参数           描述

pattern       匹配的正则表达式

string         要匹配的字符串。

flags          标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。

若匹配成功re.match方法返回一个匹配的对象,否则返回None。`

>>> s='2015-09-18'
>>> matchObj=re.match(r'\d{4}-\d{2}-\d{2}',s, flags= 0)
>>> print matchObj
<_sre.SRE_Match object at 0x7f3525480f38>
1
2
3
4
5

5.使用time.strptime提取字符串转化为时间对象

time模块中,time.strptime(str,format)可以把str按照format格式转化为时间对象,format中的常用格式有:

     %y 两位数的年份表示(00-99)

     %Y 四位数的年份表示(000-9999)

     %m 月份(01-12)

     %d 月内中的一天(0-31)

     %H 24小时制小时数(0-23)

     %I 12小时制小时数(01-12)

     %M 分钟数(00=59)

     %S 秒(00-59)

此外,还需要使用re模块,用正则表达式,对字符串进行匹配,看是否是一般时间的格式,如YYYY/MM/DD H:M:S, YYYY-MM-DD

在上面的代码中,函数catchTime就是判断item是否为时间对象,是的话转化为时间对象。

代码如下:

import time
import re

def catchTime(item):
 # check if it's time
 matchObj=re.match(r'\d{4}-\d{2}-\d{2}',item, flags= 0)
 if matchObj!= None :
  item =time.strptime(item,'%Y-%m-%d')
  #print "returned time: %s " %item
  return item
 else:
  matchObj=re.match(r'\d{4}/\d{2}/\d{2}\s\d+:\d+:\d+',item,flags=0 )
  if matchObj!= None :
   item =time.strptime(item,'%Y/%m/%d %H:%M:%S')
   #print "returned time: %s " %item
  return item

完整代码:

import collections
import time
import re

class UserInfo(object):
 'Class to restore UserInformation'
 def __init__ (self):
  self.attrilist=collections.OrderedDict()# ordered
  self.__attributes=[]
 def updateAttributes(self,attributes):
  self.__attributes=attributes
 def updatePairs(self,values):
  for i in range(len(values)):
   self.attrilist[self.__attributes[i]]=values[i]

def catchTime(item):
 # check if it's time
 matchObj=re.match(r'\d{4}-\d{2}-\d{2}',item, flags= 0)
 if matchObj!= None :
  item =time.strptime(item,'%Y-%m-%d')
  #print "returned time: %s " %item
  return item
 else:
  matchObj=re.match(r'\d{4}/\d{2}/\d{2}\s\d+:\d+:\d+',item,flags=0 )
  if matchObj!= None :
   item =time.strptime(item,'%Y/%m/%d %H:%M:%S')
   #print "returned time: %s " %item
  return item


def ObjectGenerator(maxlinenum):
 filename='/home/thinkit/Documents/usr_info/USER.csv'
 attributes=[]
 linenum=1
 a=UserInfo()
 file=open(filename)
 while linenum < maxlinenum:
  values=[]
  line=str.decode(file.readline(),'gb2312')#linecache.getline(filename, linenum,'gb2312')
  if line=='':
   print'reading fail! Please check filename!'
   break
  str_list=line.split(',')
  for item in str_list:
   item=item.strip()
   item=item.strip('\"')
   item=item.strip('\'')
   item=item.strip('+0*')
   item=catchTime(item)
   if linenum==1:
    attributes.append(item)
   else:
    values.append(item)
  if linenum==1:
   a.updateAttributes(attributes)
  else:
   a.updatePairs(values)
   yield a.attrilist #change to ' a ' to use
  linenum = linenum +1

if __name__ == '__main__':
 for n in ObjectGenerator(10):
  print n  #输出字典,看是否正确

总结

以上就是这篇文章的全部内容,希望能对大家的学习或者工作带来一定帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
深入讲解Python编程中的字符串
Oct 14 Python
Pycharm学习教程(6) Pycharm作为Vim编辑器使用
May 03 Python
Python实现的桶排序算法示例
Nov 29 Python
Sanic框架蓝图用法实例分析
Jul 17 Python
Python给定一个句子倒序输出单词以及字母的方法
Dec 20 Python
python 实现一次性在文件中写入多行的方法
Jan 28 Python
pandas DataFrame 警告(SettingWithCopyWarning)的解决
Jul 23 Python
Python 文件数据读写的具体实现
Jan 24 Python
Python多线程threading join和守护线程setDeamon原理详解
Mar 18 Python
Python 使用 PyQt5 开发的关机小工具分享
Jul 16 Python
Python中的面向接口编程示例详解
Jan 17 Python
详解Python牛顿插值法
May 11 Python
Python中字符串的处理技巧分享
Sep 17 #Python
Python中对象迭代与反迭代的技巧总结
Sep 17 #Python
发布你的Python模块详解
Sep 15 #Python
Python selenium 三种等待方式解读
Sep 15 #Python
玩转python selenium鼠标键盘操作(ActionChains)
Apr 12 #Python
Python selenium文件上传方法汇总
Nov 19 #Python
Python selenium如何设置等待时间
Sep 15 #Python
You might like
一些操作和快捷键的理解和讨论
2020/03/04 星际争霸
PHP中break及continue两个流程控制指令区别分析
2011/04/18 PHP
Mysql的Root密码忘记,查看或修改的解决方法(图文介绍)
2013/06/14 PHP
PHP实现的随机IP函数【国内IP段】
2016/07/20 PHP
php实现数字补零的方法总结
2018/09/12 PHP
用jQuery中的ajax分页实现代码
2011/09/20 Javascript
JavaScript动态操作表格实例(添加,删除行,列及单元格)
2013/11/25 Javascript
简单谈谈json跨域
2016/03/13 Javascript
javascript实现数字倒计时特效
2016/03/30 Javascript
全国省市二级联动下拉菜单 js版
2016/05/10 Javascript
bootstrap警告框示例代码分享
2017/05/17 Javascript
Angular 4依赖注入学习教程之ClassProvider的使用(三)
2017/06/04 Javascript
vue 计时器组件的实现代码
2017/09/14 Javascript
Vue2 模板template的四种写法总结
2018/02/23 Javascript
Vue实现美团app的影院推荐选座功能【推荐】
2018/08/29 Javascript
使用mpvue搭建一个初始小程序及项目配置方法
2018/12/03 Javascript
vue-cli3搭建项目的详细步骤
2018/12/05 Javascript
解决layer弹出层msg的文字不显示的问题
2019/09/11 Javascript
Python的Flask开发框架简单上手笔记
2015/11/16 Python
python实现XML解析的方法解析
2019/11/16 Python
详解Python Opencv和PIL读取图像文件的差别
2019/12/27 Python
python实现根据给定坐标点生成多边形mask的例子
2020/02/18 Python
使用celery和Django处理异步任务的流程分析
2020/02/19 Python
Python列表推导式实现代码实例
2020/09/09 Python
Python 中的函数装饰器和闭包详解
2021/02/06 Python
全球速卖通俄罗斯站:AliExpress俄罗斯
2019/06/17 全球购物
沙特阿拉伯家用电器和电子产品购物网站:Sheta and Saif
2020/04/03 全球购物
华为c/c++笔试题
2016/01/25 面试题
医院护士的求职信
2014/01/03 职场文书
党员四风问题对照检查材料
2014/09/27 职场文书
初三英语教学计划
2015/01/23 职场文书
2015年全国科普日活动总结
2015/03/23 职场文书
毕业论文致谢词
2015/05/14 职场文书
PHP命令行与定时任务
2021/04/01 PHP
Java spring单点登录系统
2021/09/04 Java/Android
js 实现Material UI点击涟漪效果示例
2022/09/23 Javascript