在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的身份证号码自动生成程序
Aug 15 Python
基于python的Tkinter实现一个简易计算器
Dec 31 Python
Python socket网络编程TCP/IP服务器与客户端通信
Jan 05 Python
Python实现字符串逆序输出功能示例
Jun 24 Python
Python numpy生成矩阵、串联矩阵代码分享
Dec 04 Python
浅谈Python Opencv中gamma变换的使用详解
Apr 02 Python
Python学习笔记之While循环用法分析
Aug 14 Python
用sqlalchemy构建Django连接池的实例
Aug 29 Python
python 使用while写猜年龄小游戏过程解析
Oct 07 Python
Python实现把类当做字典来访问
Dec 16 Python
python实现在一个画布上画多个子图
Jan 19 Python
Python  序列化反序列化和异常处理的问题小结
Dec 24 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
js实现收缩菜单效果实例代码
2013/10/30 Javascript
JavaScript中定义函数的三种方法
2015/03/12 Javascript
jQuery中 prop() attr()使用详解
2015/05/19 Javascript
JavaScript简单下拉菜单实例代码
2015/09/07 Javascript
JQuery实现级联下拉框效果实例讲解
2015/09/17 Javascript
javascript类型系统 Array对象学习笔记
2016/01/09 Javascript
jQuery form插件之formDdata参数校验表单及验证后提交
2016/01/23 Javascript
Javascript中的Prototype到底是什么
2016/02/16 Javascript
BootStrap表单验证 FormValidation 调整反馈图标位置的实例代码
2017/05/17 Javascript
微信小程序日历组件calendar详解及实例
2017/06/08 Javascript
Angular2.js实现表单验证详解
2017/06/23 Javascript
vue实现页面加载动画效果
2017/09/19 Javascript
JavaScript对象拷贝与Object.assign用法实例分析
2018/06/20 Javascript
vue 组件的封装之基于axios的ajax请求方法
2018/08/11 Javascript
vue中slot(插槽)的介绍与使用
2018/11/12 Javascript
浅谈JavaScript面向对象--继承
2019/03/20 Javascript
Vue框架下引入ActiveX控件的问题解决
2019/03/25 Javascript
vue+canvas实现拼图小游戏
2020/09/18 Javascript
原生JavaScript实现弹幕组件的示例代码
2020/10/12 Javascript
python中的hashlib和base64加密模块使用实例
2014/09/02 Python
谈谈python中GUI的选择
2018/03/01 Python
详解Python判定IP地址合法性的三种方法
2018/03/06 Python
Python使用win32 COM实现Excel的写入与保存功能示例
2018/05/03 Python
Python中文编码知识点
2019/02/18 Python
Python序列化与反序列化pickle用法实例
2019/11/11 Python
使用jupyter notebook直接打开.md格式的文件
2020/04/10 Python
python 生成器需注意的小问题
2020/09/29 Python
总结html5自定义属性有哪些
2020/04/01 HTML / CSS
ASOS比利时:英国线上零售商及自有品牌
2018/07/29 全球购物
优秀经理事迹材料
2014/02/01 职场文书
党员自我剖析材料
2014/08/31 职场文书
营销学习心得体会
2014/09/12 职场文书
小学“向国旗敬礼”网上签名寄语活动总结
2014/09/27 职场文书
公安机关查摆剖析材料
2014/10/10 职场文书
mysql 直接拷贝data 目录下文件还原数据的实现
2021/07/25 MySQL
PostgreSQL怎么创建分区表详解
2022/06/25 PostgreSQL