python實現在類中動態新增屬性和生成物件

發表於2016-09-16

程式的主要功能

現在有個儲存使用者資訊的像表格一樣的文件:第一行是屬性,各個屬性用逗號(,)分隔,從第二行開始每行是各個屬性對應的值,每行代表一個使用者。如何實現讀入這個文件,每行輸出一個使用者物件呢?
另外還有4個小要求:

  1. 每個文件都很大,如果一次性把所有行生成的那麼多物件存成列表返回,記憶體會崩潰。程式中每次只能存一個行生成的物件。
  2. 用逗號隔開的每個字串,前後可能有雙引號(”)或者單引號(’),例如”張三“,要把引號去掉;如果是數字,有+000000001.24這樣的,要把前面的+和0都去掉,提取出1.24
  3. 文件中有時間,形式可能是2013-10-29,也可能是2013/10/29 2:23:56 這樣的形式,要把這樣的字串轉成時間型別
  4. 這樣的文件有好多個,每個的屬性都不一樣,例如這個是使用者的資訊,那個是通話紀錄。所以類中的具體屬性有哪些要根據文件的第一行動態生成

下面一一進行解決

實現過程

1.類的定義

由於屬性是動態新增的,屬性-值 對也是動態新增的,類中要含有updateAttributes()和updatePairs()兩個成員函式即可,此外用列表attributes儲存屬性,詞典attrilist儲存對映。其中init()函式為建構函式。__attributes前有下劃線表示私有變數,不能在外面直接呼叫。例項化時只需a=UserInfo()即可,無需任何引數。

2.用生成器(generator)動態更新每個物件並返回物件

生成器相當於一個只需要初始化一次,就可自動執行多次的函式,每次迴圈返回一個結果。不過函式用return 返回結果,而生成器用yield 返回結果。每次執行都在yield返回,下一次執行從yield之後開始。例如,我們實現斐波拉契數列,分別用函式和生成器實現:

我們計算數列的前6個數:

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

使用方法:

可以看到,生成器fib本身是個物件,每次執行到yield會中斷返回一個結果,下次又繼續從yield的下一行程式碼繼續執行。生成器還可以用generator.next()執行,更多生成器的講解請見URL

在我的程式中,生成器部分程式碼如下:

其中,a=UserInfo()為類UserInfo的例項化.因為文件是gb2312編碼的,上面使用了對應的解碼方法。由於第一行是屬性,有個函式將屬性列表存入UserInfo中,即updateAttributes();後面的行則要將 屬性-值 對讀入一個字典中儲存。p.s.python中的字典相當於對映(map).

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

從上面程式碼中,可以看到使用str.strip(somechar)即可去除str前後的somechar字元。somechar可以是符號,也可以是正規表示式,如上:

4.re.match匹配字串

函式語法:

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

函式引數說明:
引數 描述
pattern 匹配的正規表示式
string 要匹配的字串。
flags 標誌位,用於控制正規表示式的匹配方式,如:是否區分大小寫,多行匹配等等。

若匹配成功re.match方法返回一個匹配的物件,否則返回None。`

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是否為時間物件,是的話轉化為時間物件。程式碼如下:

完整程式碼:

相關文章