英文:
Minimal implementation of a "file-like" object?
问题
我想创建一个类似文件的对象,以便传递给另一个模块。我不知道那个模块是否会调用read()
或者readline()
或者两者都会调用。如果我要继承io.IOBase
,然后只实现read()
,那是否足够,即使客户端调用readline()
呢?
奖励问题:如果我的类将以文本模式打开,那么我需要实现的最小部分是什么,以便让超类处理Unicode解码?
(这将是一个仅用于输入的类。)
元信息:我知道我可以只编写所有方法,然后查看实际调用了哪些方法,但我想要更加“未来可靠”,按照实际规范编写代码,而不是尝试各种方法来查看它们是否有效,然后在未来某一天出现问题。
英文:
I want to create a file-like object to be passed to another module. I don't know if that other module will be calling read() or readline() or both. If I were to subclass say io.IOBase
and just implement read()
would that be sufficient, even if the client is calling readline()
?
Bonus question: if my class will be opened in text mode, what's the minimum I can implement to let the superclass handle the unicode decoding?
(This will be an input-only class.)
Meta: I know I could just write all the methods and see what actually gets called, but I'd like to be a bit "future proof" and write to the actual specs, instead of trying things to see if they work, and then having them break in the future someday.
答案1
得分: 3
从经验上看,实现read
将足够。
至于文本模式,您只需使用TextIOWrapper
(技术上应该与BufferedIOBase
一起使用,但看起来与IOBase
也能正常工作)。
import io
class FooIO(io.IOBase):
def __init__(self, buffer):
self.buffer = buffer
self.pos = 0
def rewind(self):
self.pos = 0
def readable(self) -> bool:
return True
def read(self, size=-1):
if size == -1:
size = len(self.buffer) - self.pos
data = self.buffer[self.pos:self.pos + size]
self.pos += size
return data
f = FooIO(b"hello\nworld\nthis\nis\na\ntest")
for x in range(7):
print(x, f.readline())
f.rewind()
tiow = io.TextIOWrapper(f)
for x in range(7):
print(x, repr(tiow.readline()))
打印结果如下:
0 b'hello\n'
1 b'world\n'
2 b'this\n'
3 b'is\n'
4 b'a\n'
5 b'test'
6 b''
0 'hello\n'
1 'world\n'
2 'this\n'
3 'is\n'
4 'a\n'
5 'test'
6 ''
英文:
Empirically, implementing read
will be enough.
As for text mode, you'd want to just use TextIOWrapper
(which technically is meant to be used with a BufferedIOBase
, but it looks like things work with IOBase
too).
import io
class FooIO(io.IOBase):
def __init__(self, buffer):
self.buffer = buffer
self.pos = 0
def rewind(self):
self.pos = 0
def readable(self) -> bool:
return True
def read(self, size=-1):
if size == -1:
size = len(self.buffer) - self.pos
data = self.buffer[self.pos:self.pos + size]
self.pos += size
return data
f = FooIO(b"hello\nworld\nthis\nis\na\ntest")
for x in range(7):
print(x, f.readline())
f.rewind()
tiow = io.TextIOWrapper(f)
for x in range(7):
print(x, repr(tiow.readline())))
prints out
0 b'hello\n'
1 b'world\n'
2 b'this\n'
3 b'is\n'
4 b'a\n'
5 b'test'
6 b''
0 'hello\n'
1 'world\n'
2 'this\n'
3 'is\n'
4 'a\n'
5 'test'
6 ''
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论