この記事では以下のような観点から一つ一つ解決していきます
1. プログラムの主な機能
2. 実装プロセス
3. クラス定義
4. ジェネレータージェネレーターによる動的更新 それぞれオブジェクトを取得し、オブジェクトを返します
5. ストリップを使用して不要な文字を削除します
6. 一致する文字列を再照合します 7. timestrptime を使用して文字列を抽出し、時刻オブジェクトに変換します 8. 完全なコード
これで、ユーザー情報を格納するテーブルのようなドキュメントができました。最初の行は属性で、各属性はカンマ (,) で区切られ、2 行目以降、各行は以下に対応します。各属性の値、各行はユーザーを表します。このドキュメントを読んで、1 行に 1 つのユーザー オブジェクトを出力するにはどうすればよいですか? さらに 4 つの小さな要件があります: すべての行によって生成された多数のオブジェクトがリストに格納され、一度に返されると、メモリが崩壊します。プログラムに一度に保存できる行生成オブジェクトは 1 つだけです。
コンマで区切られた各文字列の前後に二重引用符 (") または一重引用符 (') を付けることができます。たとえば、「Zhang San」の場合は引用符を削除する必要があります。+000000001.24 などの数値の場合は、引用符を削除する必要があります。先頭の + と 0 を削除して 1.24 を抽出します
文書内に 2013-10-29 の形式である可能性がある、または 2013/ の形式である可能性があります。 10/29 2:23:56. このような文字列を取得するには、時刻型に変換します
このようなドキュメントは多数あり、それぞれ異なる属性があります。たとえば、これはユーザー情報であり、これは通話記録です。クラス内の属性は、ドキュメントの最初の行に基づいて動的に生成される必要があります
1. クラス定義 属性は動的に追加されるため、属性と値のペアも動的に追加されます。 、クラスには updateAttributes()
と updatePairs()
が含まれている必要があります。さらに、リスト attributes
を使用して属性を保存します。辞書 attrilist
はマッピングを保存するために使用されます。 ) 関数は、__attributes
の前のアンダースコアはプライベート変数を示し、外部から直接呼び出すことはできません。パラメータを指定せずに、 a=UserInfo()
だけをインスタンス化に使用できます。
2. ジェネレーターを使用して各オブジェクトを動的に更新します
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
このジェネレーターは、一度初期化するだけで済み、自動的に複数回実行できるジェネレーターと同等ですが、この関数は結果を返すために return
を使用します。 、ジェネレーターは実行されるたびに yield
を使用して結果を返し、次の実行は yield
の後に開始されます。たとえば、フィボナッチ数列を実装します。関数とジェネレーターをそれぞれ使用します:
item=item.strip()#除去字符串前后的所有转义字符,如\t,\n等 item=item.strip('\"')#除去前后的" item=item.strip('\'') item=item.strip('+0*')#除去前后的+00...00,*表示0的个数可以任意多,也可以没有
シーケンスの最初の 6 を計算します。数値: re.match(pattern, string, flags=0)
print
を < に変更するだけです。 code>yield は次のようになります: 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 #输出字典,看是否正确
yield
の次のコード行から実行を継続します。 generator.next()
を使用してジェネレーターを実行することもできます。 私のプログラムでは、ジェネレーター部分のコードは次のとおりです:
rrreee
a=UserInfo( )
はクラス UserInfo
のインスタンス化です。ドキュメントは gb2312 でエンコードされているため、対応するデコード方法が上記で使用されています。最初の行は属性であるため、UserInfo
に属性リストを格納する関数、つまり updateAttributes();
があり、次の行は属性を読み取る必要があります。値のペアを辞書に格納します。 p.s.python
の辞書はマップに相当します🎜🎜🎜🎜3. 不要な文字を削除するには、strip を使用します🎜🎜🎜🎜🎜 上記のコードから、 str を使用していることがわかります。 strip(somechar)
は、str の前後の somechar
文字を削除できます。 somechar
は、上記のように、シンボルまたは正規表現にすることができます: 🎜🎜🎜rrreee🎜🎜🎜🎜🎜4.re.match 一致する文字列 🎜🎜🎜🎜🎜関数の構文: 🎜🎜🎜rrreee明関数パラメーターの説明: 🎜🎜🎜 パラメーターの説明 🎜🎜🎜パターン マッチング正規表現 🎜🎜🎜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 #输出字典,看是否正确
总结
以上就是这篇文章的全部内容,希望能对大家的学习或者工作带来一定帮助,如果有疑问大家可以留言交流,谢谢大家对PHP中文网的支持。
更多在python的类中动态添加属性与生成对象相关文章请关注PHP中文网!