как быстро работает срез python

чтобы сэкономить место и сложность поддержания согласованности данных между различными источниками, я рассматриваю возможность хранения индексов начала/конца для некоторых подстрок вместо хранения самих подстрок. Фокус в том, что если я это сделаю, возможно, я буду создавать срезы все время. Стоит ли этого избегать? Достаточно ли быстр оператор slice, мне не нужно беспокоиться? Как насчет накладных расходов на создание/уничтожение нового объекта?


ОК, Я усвоил урок. Не оптимизируйте, если нет реальной проблемы, которую вы пытаетесь исправить. (Конечно, это не означает, что нужно исправлять бесполезно плохой код, но это не имеет значения...) Кроме того, тест и профиль перед приходом в Stack overflow. =D Спасибо всем!

5 ответов


  1. достаточно быстро, в отличие от чего? Как ты это делаешь прямо сейчас? Что именно вы храните, что именно вы получаете? Ответ, вероятно, сильно зависит от этого. Что приводит нас к этому ...

  2. меру! Не обсуждайте и не анализируйте теоретически; попробуйте измерить, что является более эффективным способом. Затем решите, оправдывает ли возможный прирост производительности рефакторинг вашей базы данных.

Edit: I просто запустил тест измерения строки нарезки по сравнению с поиском в Дикте, набранном на (start, end) ОК. Это говорит о том, что особой разницы нет. Это довольно наивный тест, так что возьмите его с щепоткой соли.


в комментарии OP упоминает раздувание "в базе данных", но никакой информации о том, о какой базе данных он говорит; из скудной информации в этом комментарии казалось бы, что срезы строк Python не обязательно являются тем, что связано, скорее," срезание " будет сделано механизмом БД после извлечения.

Если это реальная ситуация, то я бы рекомендовал по общим принципам против хранения избыточной информации в БД -- "нормальная форма" (возможно, в слабом смысле выражения; -) при котором информация хранится только один раз и производная информация пересчитывается (или кэшируется заряд двигателя БД и т. д.;-) должна быть нормой, а "денормализация" путем преднамеренного хранения производной информации-очень большим исключением и только тогда, когда это оправдано конкретными, хорошо измеренными потребностями в производительности поиска.

Если ссылка на "базу данных" была неправильным направлением; -), или, скорее, используется в слабом смысле, как я сделал для" нормальной формы " выше; -), то другое соображение может применяться: поскольку строки Python неизменяемы, казалось бы, было бы естественным не делать срезы путем копирования, а скорее иметь каждый срез повторно использовать часть пространства памяти родителя, из которого он нарезается (так же, как это делается для срезов массивов numpy). Однако в настоящее время это не часть ядра Python. Я однажды попробовал патч для этой цели, но проблема добавления ссылки на большую строку и, таким образом, ее сохранения в памяти только потому, что на нее все еще ссылается крошечная подстрока замаячил большой для общецелевой адаптации. Тем не менее, можно было бы сделать специальный подкласс string (и один из unicode) для случая, когда большая "родительская" строка все равно должна оставаться в памяти. В настоящее время buffer делает немного этого, но вы не можете вызывать строковые методы на объекте буфера (без явного копирования его в объект string), поэтому он действительно полезен только для вывода и нескольких особых случаев... но нет никакого реального концептуального блока против добавления строки метод (я сомневаюсь, что он будет принят в ядре, но он должен быть прилично прост в обслуживании в качестве стороннего модуля;-).

ценность такого подхода вряд ли может быть убедительно доказана измерением, так или иначе-скорость будет очень похожа на текущий подход неявного копирования; преимущество будет полностью заключаться в сокращении объема памяти, что не столько сделает любой данный код Python быстрее, но скорее позволит определенной программе выполняться на компьютере. машина с немного меньшим ОЗУ или многозадачность лучше, когда несколько экземпляров используются одновременно в отдельных процессах. См.трос для аналогичного, но более богатого подхода, когда-то экспериментировавшего в контексте C++ (но обратите внимание, что он не попал в стандарт; -).


я тоже не делал никаких измерений, но поскольку похоже, что вы уже используете подход C к проблеме в Python, вы можете взглянуть на встроенный Python mmap библиотека:

сопоставленные с памятью файловые объекты ведут себя как строки и как файловые объекты. Однако, в отличие от обычных строковых объектов, они изменчивы. Объекты mmap можно использовать в большинстве мест, где ожидаются строки; например, можно использовать модуль re для поиска через отображаемый в память файл. Поскольку они изменчивы, вы можете изменить один символ, выполнив obj[index] = 'a', или изменить подстроку, назначив срезу: obj[i1:i2] = '...'. Вы также можете читать и записывать данные, начиная с текущей позиции файла, и искать() через файл в разные позиции.

Я не уверен, из вашего вопроса, если это именно то, что вы ищете. И стоит повторить, что вам нужно сделать некоторые измерения. в Python timeit библиотека является простым в использовании, но есть также cProfile или hotshot, хотя hotshot рискует быть удален из стандартной библиотеки, как я понимаю.


будут ли срезы неэффективными, потому что они создают копии исходной строки? Это может быть проблемой, а может и нет. Если это окажется проблемой, невозможно будет просто реализовать "строковое представление"; объект, который имеет ссылку на исходную строку и имеет начальную и конечную точки.. При доступе / итерации он просто считывает из исходной строки.


преждевременная оптимизация-это Рул всех зол.

докажите себе, что вам действительно нужно оптимизировать код, а затем действовать.