Python相当于Java StringBuffer?

use*_*773 64 python java stringbuffer

像Java这样的Python中有什么东西StringBuffer吗?由于字符串在Python中也是不可变的,因此在循环中编辑它们效率很低.

geo*_*org 68

Python中的高效字符串连接是一篇相当古老的文章,它的主要陈述是天真连接比连接慢得多,因为这部分已经在CPython中进行了优化:

CPython实现细节:如果s和t都是字符串,某些Python实现(如CPython)通常可以对s = s + t或s + = t形式的赋值执行就地优化.如果适用,此优化使得二次运行时间的可能性大大降低.此优化依赖于版本和实现.对于性能敏感的代码,最好使用str.join()方法,该方法确保跨版本和实现的一致的线性串联性能.@ http://docs.python.org/2/library/stdtypes.html

我已经调整了他们的代码并在我的机器上得到了以下结果:

from cStringIO import StringIO
from UserString import MutableString
from array import array

import sys, timeit

def method1():
    out_str = ''
    for num in xrange(loop_count):
        out_str += `num`
    return out_str

def method2():
    out_str = MutableString()
    for num in xrange(loop_count):
        out_str += `num`
    return out_str

def method3():
    char_array = array('c')
    for num in xrange(loop_count):
        char_array.fromstring(`num`)
    return char_array.tostring()

def method4():
    str_list = []
    for num in xrange(loop_count):
        str_list.append(`num`)
    out_str = ''.join(str_list)
    return out_str

def method5():
    file_str = StringIO()
    for num in xrange(loop_count):
        file_str.write(`num`)
    out_str = file_str.getvalue()
    return out_str

def method6():
    out_str = ''.join([`num` for num in xrange(loop_count)])
    return out_str

def method7():
    out_str = ''.join(`num` for num in xrange(loop_count))
    return out_str


loop_count = 80000

print sys.version

print 'method1=', timeit.timeit(method1, number=10)
print 'method2=', timeit.timeit(method2, number=10)
print 'method3=', timeit.timeit(method3, number=10)
print 'method4=', timeit.timeit(method4, number=10)
print 'method5=', timeit.timeit(method5, number=10)
print 'method6=', timeit.timeit(method6, number=10)
print 'method7=', timeit.timeit(method7, number=10)
Run Code Online (Sandbox Code Playgroud)

结果:

2.7.1 (r271:86832, Jul 31 2011, 19:30:53) 
[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)]
method1= 0.171155929565
method2= 16.7158739567
method3= 0.420584917068
method4= 0.231794118881
method5= 0.323612928391
method6= 0.120429992676
method7= 0.145267963409
Run Code Online (Sandbox Code Playgroud)

结论:

  • join 仍然胜过concat,但略有不同
  • 列表推导比循环更快
  • 加入生成器比加入列表慢
  • 其他方法没用(除非你做了特别的事)

  • MutableString 类在 Python 2.6 中已被弃用并在 Python 3 中完全删除可能毫无价值。请参阅 [此处](https://docs.python.org/2/library/userdict.html?highlight=mutablestring#UserString .MutableString) (3认同)
  • 警告!CPython对此进行优化的说法在最近的版本(v3.5-v3.8+)中不再适用。这已被替换为警告,以这种方式连接不可变对象_始终_是二次的:https://docs.python.org/3/library/stdtypes.html (2认同)

unu*_*tbu 11

也许使用bytearray:

In [1]: s = bytearray('Hello World')

In [2]: s[:5] = 'Bye'

In [3]: s
Out[3]: bytearray(b'Bye World')

In [4]: str(s)
Out[4]: 'Bye World'
Run Code Online (Sandbox Code Playgroud)

使用bytearray的吸引力在于其内存效率和方便的语法.它也比使用临时列表更快:

In [36]: %timeit s = list('Hello World'*1000); s[5500:6000] = 'Bye'; s = ''.join(s)
1000 loops, best of 3: 256 µs per loop

In [37]: %timeit s = bytearray('Hello World'*1000); s[5500:6000] = 'Bye'; str(s)
100000 loops, best of 3: 2.39 µs per loop
Run Code Online (Sandbox Code Playgroud)

请注意,速度的很大差异可归因于容器的创建:

In [32]: %timeit s = list('Hello World'*1000)
10000 loops, best of 3: 115 µs per loop

In [33]: %timeit s = bytearray('Hello World'*1000)
1000000 loops, best of 3: 1.13 µs per loop
Run Code Online (Sandbox Code Playgroud)


bru*_*ers 11

取决于你想做什么.如果你想要一个可变序列,内置list类型是你的朋友,从str到list然后返回就像这样简单:

 mystring = "abcdef"
 mylist = list(mystring)
 mystring = "".join(mylist)
Run Code Online (Sandbox Code Playgroud)

如果你想使用for循环构建一个大字符串,pythonic方法通常是建立一个字符串列表,然后将它们与适当的分隔符(换行符或其他)连接在一起.

此外,您还可以使用一些文本模板系统,或者解析器或任何专门用于工作的专用工具.


rha*_*l80 5

以前提供的答案几乎总是最好的.但是,有时字符串是在许多方法调用和/或循环中构建的,因此构建行列表然后加入它们并不一定很自然.由于无法保证您使用CPython或CPython的优化将适用,因此另一种方法是使用print!

这是一个示例帮助程序类,虽然帮助程序类很简单并且可能是不必要的,但它用于说明该方法(Python 3):

import io

class StringBuilder(object):

  def __init__(self):
    self._stringio = io.StringIO()

  def __str__(self):
    return self._stringio.getvalue()

  def append(self, *objects, sep=' ', end=''):
    print(*objects, sep=sep, end=end, file=self._stringio)

sb = StringBuilder()
sb.append('a')
sb.append('b', end='\n')
sb.append('c', 'd', sep=',', end='\n')
print(sb)  # 'ab\nc,d\n'
Run Code Online (Sandbox Code Playgroud)


Kam*_*rya 3

此链接对于 python 中的串联可能有用

http://pythonadventures.wordpress.com/2010/09/27/stringbuilder/

上面链接中的示例:

def g():
    sb = []
    for i in range(30):
        sb.append("abcdefg"[i%7])

    return ''.join(sb)

print g()   

# abcdefgabcdefgabcdefgabcdefgab
Run Code Online (Sandbox Code Playgroud)