在Python中存储字符串的对象

1 投票
2 回答
2367 浏览
提问于 2025-04-15 20:21
class MyWriter:

    def __init__(self, stdout):
        self.stdout = stdout
        self.dumps = []

    def write(self, text):
        self.stdout.write(smart_unicode(text).encode('cp1251'))
        self.dumps.append(text)

    def close(self):
        self.stdout.close()   

writer = MyWriter(sys.stdout)
save = sys.stdout
sys.stdout = writer 

我用 self.dumps 这个列表来存储从打印中得到的数据。有没有更方便的方式来把字符串行存储在内存里呢?理想情况下,我想把它们合成一个大字符串。我可以用上面的代码 "\n".join(self.dumps) 来做到这一点。也许直接把字符串拼接在一起会更好,比如 self.dumps += text

2 个回答

1

我很确定,使用 '\n'.join(self.dumps) 会比 self.dumps += text 快得多。

解释:在Python中,字符串是不可变的,这意味着如果你把两个字符串拼接在一起,就会生成一个新的字符串,并把原来的两个字符串复制到这个新字符串里。如果你只做一次,这没什么问题,但如果在一个循环里这样做,每次循环都会复制整个文本。另一方面,join() 是一个用C语言写的内置函数,它能有效地重新分配内存并改变字符串的结尾。所以,它应该会快很多。

所以,你的代码完全没问题。干得好!

附注:缺少了 flush() 函数。

2

要把一堆字符串合成一个字符串,用 ''.join 是个不错的方法。不过,如果你想要更直接的解决办法:

import cStringIO

class MyWriter(object):

    def __init__(self, stdout):
        self.stdout = stdout
        self.dumps = cStringIO.StringIO()
        self.final = None

    def write(self, text):
        self.stdout.write(smart_unicode(text).encode('cp1251'))
        self.dumps.write(text)

    def close(self):
        self.stdout.close()
        self.final = self.dumps.getvalue()
        self.dumps.close()

    def getvalue(self):
        if self.final is not None:
            return self.final
        return self.dumps.getvalue()

getvalue 这个方法在字符串输入输出对象(string-io)关闭后是不能调用的,因为关闭对象会让它丢掉自己的缓存内存。所以我在关闭之前就把 self.final 设定好了。除了 getvalue,字符串输入输出对象基本上是一个很好的“像文件一样的对象”的实现,所以当你想把原本设计用来 print 输出结果的代码改成把结果保存在内存中时,它就特别有用了;而且这也是一个很好的方法来“逐步构建一个字符串”——只需要用 write 写入每一部分,完成后(或者在任何时候)用 getvalue 查看你到目前为止构建的内容。

现代 Python 的风格通常是更倾向于低抽象的方法(明确地构建一个字符串列表,然后在需要的时候把它们合成一个字符串),但使用稍微高抽象的“字符串输入输出”方法也没有问题。

(还有一种方法似乎不太流行,就是不断地用 extend 来扩展一个 array.array 的字符数组,只是为了全面列出这些方法;-)

撰写回答