Манипулирование строками в Python - PullRequest
1 голос
/ 07 апреля 2009

Я конвертирую некоторый код с другого языка в python. Этот код считывает довольно большой файл в строку, а затем манипулирует им путем индексации массива, например:

str[i] = 'e'

Это не работает напрямую в python из-за неизменяемости строк. Каков предпочтительный способ сделать это в Python?

Я видел функцию string.replace(), но она возвращает копию строки, которая звучит не очень оптимально, поскольку строка в этом случае является целым файлом.

Ответы [ 4 ]

12 голосов
/ 07 апреля 2009

Если вы не используете кодировку текста переменной длины, например UTF-8, вы можете использовать array.array:

>>> import array
>>> a = array.array('c', 'foo')
>>> a[1] = 'e'
>>> a
array('c', 'feo')
>>> a.tostring()
'feo'

Но так как вы имеете дело с содержимым файла, 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

Вот скрипт быстрого бенчмаркинга (вам нужно заменить dd чем-то другим для не-Unix ОС):

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)

Вывод, полученный на моем ноутбуке, которому несколько лет, соответствует моей интуиции:

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

Таким образом, mmap немного быстрее, но ни одно из предложенных решений особо не отличается. Если вы видите огромную разницу, попробуйте использовать cProfile , чтобы увидеть, что занимает время.

9 голосов
/ 07 апреля 2009
l = list(str)
l[i] = 'e'
str = ''.join(l)
1 голос
/ 07 апреля 2009

Другие ответили на вопрос о работе со строками в вашем вопросе, но я думаю, вам следует подумать о том, лучше ли будет проанализировать файл и изменить структуру данных, которую представляет текст, а не манипулировать текстом напрямую.

0 голосов
/ 07 апреля 2009

Попробуйте:

sl = list(s)
sl[i] = 'e'
s = ''.join(sl)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...