我想在open()
函数周围堆叠过滤器。例如,假设这些过滤器将从文件中读取的流中的每个遇到的a
个字符更改为b
。
例如,这是一个代码示例:
def filter (stream):
for line in stream:
yield line.replace('a', 'b')
def add_filter(filter, file):
return io.TextIOWrapper(filter(file))
def processing_file(f):
import sys
for line in f:
sys.stdout.write("aa: " + line)
f = open('./example.txt', 'r')
f = add_filter(filter, f)
processing_file(f)
我想filter_a()
函数应返回TextIOWrapper
来模仿open()
函数的结果。但是,我一直有以下错误消息:
AttributeError: 'generator' object has no attribute 'readable'
事实上,我理解错误,但我不知道如何解决并使其正常工作。
答案 0 :(得分:3)
您可以直接在过滤器生成器上进行迭代:
with open('./example.txt', 'r') as f:
for line in filter(f):
sys.stdout.write("aa: " + line)
答案 1 :(得分:1)
我找到了解决自己问题的方法......首先,我必须承认我的问题并不完全正确,可能缺乏精确性。所以,我不怪任何人放弃它。
我的初衷是在流(open()
)上提供可堆叠的过滤器框架。试图让它易于使用,也是。
我主要在StackOverflow上的这个answer中找到灵感,它解决了我约90%的问题。
因此,假设我们有两个过滤器(编码为生成器):
def tab_filter(stream):
for line in stream:
yield line.replace ('\t', ' ' * 8)
def a_filter(stream):
for line in stream:
yield line.replace ('a', 'z')
然后,我们有这个类允许将一个生成器包装在一个流中:
class IterStream(object):
"File-like streaming iterator."
def __init__(self, generator):
self.generator = generator
self.iterator = iter(generator)
self.leftover = ''
def __len__(self):
return self.generator.__len__()
def __iter__(self):
return self.iterator
def next(self):
return self.iterator.next()
def read(self, size):
data = self.leftover
count = len(self.leftover)
try:
while count < size:
chunk = self.next()
data += chunk
count += len(chunk)
except StopIteration:
self.leftover = ''
return data
if count > size:
self.leftover = data[size:]
return data[:size]
在代码中使用它将如下:
import sys
f = IterStream(a_filter(IterStream(tab_filter(open('Example.txt', 'r')))))
for line in f:
sys.stdout.write("aa: " + line)
但是,这还不完全令人满意,因为我们需要大量无用的功能堆叠。所以,我决定将它包装在装饰器中:
def streamfilter(filter): def stream(iostream): return IterStream(filter(iostream)) return stream @streamfilter def tab_filter(stream): for line in stream: yield line.replace ('\t', ' ' * 8) @streamfilter def a_filter(stream): for line in stream: yield line.replace ('a', 'z')
然后,现在使用代码要容易得多:
import sys
f = a_filter(tab_filter(open('Example.txt', 'r')))
for line in f:
sys.stdout.write("aa: " + line)
我希望你们中的一些人会发现这几行很有用。