Python中的字符串操作

Zit*_*rax 1 python string replace

我正在将一些代码从另一种语言转换为python.该代码将一个相当大的文件读入一个字符串,然后通过数组索引操作它,如:

str[i] = 'e'
Run Code Online (Sandbox Code Playgroud)

由于字符串是不可变的,这在python中不起作用.在python中执行此操作的首选方法是什么?

我已经看过该string.replace()函数,但它返回的字符串副本听起来不是很理想,因为在这种情况下字符串是整个文件.

Nic*_*ley 12

假设您没有使用可变长度的文本编码,例如UTF-8,您可以使用array.array:

>>> import array
>>> a = array.array('c', 'foo')
>>> a[1] = 'e'
>>> a
array('c', 'feo')
>>> a.tostring()
'feo'
Run Code Online (Sandbox Code Playgroud)

但是,由于您正在处理文件的内容,因此mmap应该更有效:

>>> f = open('foo', 'r+')
>>> import mmap
>>> m = mmap.mmap(f.fileno(), 0)
>>> m[:]
'foo\n'
>>> m[1] = 'e'
>>> m[:]
'feo\n'
>>> exit()
% cat foo
feo
Run Code Online (Sandbox Code Playgroud)

这是一个快速的基准测试脚本(你需要用非Unix操作系统的其他东西替换dd):

import os, time, array, mmap

def modify(s):
    for i in xrange(len(s)):
        s[i] = 'q'

def measure(func):
    start = time.time()
    func(open('foo', 'r+'))
    print func.func_name, time.time() - start

def do_split(f):
    l = list(f.read())
    modify(l)
    return ''.join(l)

def do_array(f):
    a = array.array('c', f.read())
    modify(a)
    return a.tostring()

def do_mmap(f):
    m = mmap.mmap(f.fileno(), 0)
    modify(m)

os.system('dd if=/dev/random of=foo bs=1m count=5')

measure(do_mmap)
measure(do_array)
measure(do_split)
Run Code Online (Sandbox Code Playgroud)

我用几年前的笔记本电脑输出的输出符合我的直觉:

5+0 records in
5+0 records out
5242880 bytes transferred in 0.710966 secs (7374304 bytes/sec)
do_mmap 1.00865888596
do_array 1.09792494774
do_split 1.20163106918
Run Code Online (Sandbox Code Playgroud)

因此mmap稍微快一些,但建议的解决方案都没有特别的不同.如果您看到了巨大的差异,请尝试使用cProfile查看花费时间的内容.


Can*_*der 9

l = list(str)
l[i] = 'e'
str = ''.join(l)
Run Code Online (Sandbox Code Playgroud)