本文將透過幾個面向來解決
1、程式的主要功能
## 完整程式碼
程式的主要功能
#現在有個儲存使用者資訊的像表格一樣的文件:第一行是屬性,各個屬性以逗號(,)分隔,從第二行開始每行是各個屬性對應的值,每行代表一個使用者。如何實現讀入這個文檔,每行輸出一個使用者物件呢? 另外還有4個小要求:每個文件都很大,如果一次把所有行產生的那麼多物件存成列表返回,記憶體會崩潰。程式中每次只能存一個行所產生的物件。
用逗號隔開的每個字串,前後可能有雙引號(”)或單引號('),例如”張三“,要把引號去掉;如果是數字,有+000000001.24這樣的,要把前面的+和0都去掉,提取出1.24
實作過程
1.類別的定義
#由於屬性是動態新增的,屬性-值對也是動態新增的,類別中要包含updateAttributes()和
updatePairs()
attributes儲存屬性,字典
attrilist儲存映射。前有底線表示私有變量,不能在外面直接呼叫。
##2.用生成器(generator)動態更新每個物件並傳回物件
產生器相當於一個只需要初始化一次,就可自動執行多次的函數,每次迴圈回傳一個結果。 ##yield
返回,下次運行從yield
之後開始。
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]
就可以了。 ##可以看到,生成器fib本身就是個對象,每次執行到yield會中斷回傳一個結果,下次又繼續從
yield
的下一行程式碼繼續執行。器也可以用generator.next()
執行。 在我的程式中,生成器部分程式碼如下:
def fib(max): n, a, b = 0, 0, 1 while n < max: print(b) a, b = b, a + b n = n + 1 return 'done'
其中,
a=UserInfo()為類別
UserInfo的實例化.因為文件是gb2312編碼的,上面使用了對應的解碼方法。由於第一行是屬性,所以有函數將屬性清單存入
UserInfo中,即updateAttributes();
後面的行則要將屬性-值對讀入一個字典中儲存。 p.s.python
中的字典相當於映射(map).
3.使用strip 移除不必要的字元
從上面程式碼中,可以看到使用str.strip(somechar)
即可移除str前後的somechar字元。
somechar可以是符號,也可以是正規表示式,如上:
#
>>> fib(6) 1 1 2 3 5 8 'done'
函數語法:
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:py;">def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1</pre><div class="contentsignin">登入後複製</div></div>
函數參數說明:
參數 說明#pattern 符合的正規表示式
string string
<p>flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。</p><p>若匹配成功re.match方法返回一个匹配的对象,否则返回None。`</p><p>>>> s='2015-09-18'<br/>>>> matchObj=re.match(r'\d{4}-\d{2}-\d{2}',s, flags= 0)<br/>>>> print matchObj<br/><_sre.SRE_Match object at 0x7f3525480f38><br/>1<br/>2<br/>3<br/>4<br/>5<br/></p><p><span style="color: #ff0000"><strong>5.使用time.strptime提取字符串转化为时间对象</strong></span><br/></p><p>在<code>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 #输出字典,看是否正确
总结
以上就是这篇文章的全部内容,希望能对大家的学习或者工作带来一定帮助,如果有疑问大家可以留言交流,谢谢大家对PHP中文网的支持。
更多在python的类中动态添加属性与生成对象相关文章请关注PHP中文网!