2016-08-11 65 views
0

我有一個讀取大文件(我在這裏簡單的閱讀一個非常小的Excel文件)的2個不同版本的函數。蟒蛇 - 裝飾一個發電機

Version 1:閱讀整篇文件,並返回行列表
Version 2:與發電機的幫助下讀它一行行

我想裝飾這些2個函數的輸出,並添加了一些每行結束基於不同的邏輯,這就是爲什麼我認爲我需要不同的定製裝飾。但我無法弄清楚如何通過裝飾者的幫助來實現它?特別是如果我有收益而不是回報。

版本1:

@dec 
def readxls(): 
    fileBook = xlrd.open_workbook('../decorator.xls') 
    sh = fileBook.sheet_by_name("Sheet1") 
    out = [] 
    for row_index in xrange(1, sh.nrows): 
     out.append(sh.row_values(row_index)) 
    return out 

版本2:

@dec2 
def readxls(): 
    fileBook = xlrd.open_workbook('../decorator.xls') 
    sh = fileBook.sheet_by_name("Sheet1") 
    for row_index in xrange(1, sh.nrows): 
     yield sh.row_values(row_index) 

假設Excel文件是這樣的:

Col1 Col2 Col3 
Val11 Val12 Val13 
Val21 Val22 Val23 

我想裝飾的輸出得到以下結果:

Col1 Col2 Col3 0 Col1Col2 
Val11 Val12 Val13 1 Val11Val12 
Val21 Val22 Val23 2 Val21Val22 

爲了得到類似這樣的輸出,我的dec1和dec2函數應該如何?

回答

1

裝飾者設想工作一個採取的功能的結果操縱它並給出新的結果,所以知道結果是關鍵,在這種情況下,對於這個例子,結果是版本1的[['val11', 'val12', 'val13'], ['val21', 'val22', 'val23']]和發電機與第二個的元素。有了這些知識,我們可以繼續做裝飾,例如像

from functools import wraps 

def decorator1(fun): 
    @wraps(fun) 
    def wrapper(*args,**kwds): 
     result = fun(*args,**kwds) 
     for i,x in enumerate(result,1): 
      x.extend((i, x[0]+x[1])) 
     return result 
    return wrapper 

def decorator2(fun): 
    @wraps(fun) 
    def wrapper(*args,**kwds): 
     for i,x in enumerate(fun(*args,**kwds),1): 
      x.extend((i, x[0]+x[1])) 
      yield x 
    return wrapper 

(這裏我用wraps,以幫助維持裝飾功能的一些元數據(聰明並不需要的功能),併爲嚮導,以寫例如)

在第一個裝飾器中,因爲結果是整個列表,所以我只是將多餘的東西添加到每個元素並返回它,並在第二次添加額外的東西,因爲他們一起維護生成器結構

裝飾着那些,結果現在是[['val11', 'val12', 'val13', 1, 'val11val12'], ['val21', 'val22', 'val23', 2, 'val21val22']]


順便注意,因爲你的2個功能做同樣的事情,我寧願保持發電機,當我需要一個列表呼叫list(readxls())和我也將增加2個額外的變量與默認值的函數簽名這些字符串使功能更加靈活。