我有2个不同版本的功能;它读取一个大文件(我在这里简单一点,读取一个非常小的excel文件)。
Version 1:
阅读整个文件并返回行列表
Version 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函数应该如何?
答案 0 :(得分:1)
装饰器假设使用函数的结果来操作它并给出新结果,因此知道结果是什么是键,在这种情况下,对于该示例,结果是[['val11', 'val12', 'val13'], ['val21', 'val22', 'val23']]
版本1和一个发电机,其元件为第二个。有了这些知识,我们可以继续制作一个装饰器,例如
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个额外的变量,默认值那些字符串使功能更加灵活。