Як швидко конкатенувати рядки в Python?


Дізнайтесь більше про нові кар'єрні можливості в EchoUA. Цікаві проекти, ринкова оплата, гарний колектив. Надсилайте резюме та приєднуйтеся до нас.

Розповідає Рювен Лернер, викладач


Як Ви, напевно, знаєте один з принципів у Python: “Має бути один і тільки один спосіб зробити що-небудь”. Можете переконатися в цьому, виконавши у в інтерпретаторі import this (Ви побачите Дзен Python). Незважаючи на це, іноді Вам все одно доводиться вибирати між декількома способами зробити щось, і не завжди очевидно, який спосіб кращий. Нещодавно студент запитав у мене: “Який спосіб конкатенації рядків у Python є найефективнішим?”. Я вирішив поділитися результатом свого маленького дослідження також з Вами.

Спочатку згадаємо, які способи об’єднання рядків надає нам Python. По-перше, це оператор +:

>> 'abc' + 'def''abcdef'

Ми можемо використати оператор %, який, звичайно, використовується не лише для об’єднання рядків, але й для цього:

>>> "%s%s" %  ('abc', 'def') 'abcdef'

Є сучасніша заміна % – це str.format:

>>> '{0}{1}'.format ('abc', 'def') 'abcdef'

Так само, як і %, цей метод набагато потужніший, ніж звичайний +, проте рядки поєднують і за його допомогою.

Як же ми замірятимемо час? У Jupyter (так само відомому, як IPython) ми можемо використати магічну команду timeit для запуску коду. Для запуску я підготував чотири функції, кожна з яких складає рядки різним чином. Початкові рядки зберігаються в глобальних змінних (x і y), а локальна (для кожної функції) змінна z містить результат складання. Потім функція повертає результат.

def concat1 (): z = x + y return z def concat2 (): z = "%s%s" %  (x, y) return z def concat3 (): z = "{}{}".format (x, y) return z def concat4 (): z = "{0}{1}".format (x, y) return z

Звичайно concat3 () і concat4 () фактично однакові, але я вирішив перевірити і те, впливає вказівка порядку рядків на швидкість або ні. Потім я визначив наші глобальні змінні:

x = 'abc' y = 'def'

І запустив наші функції:

%timeit concat1 ()%timeit concat2 ()%timeit concat3 ()%timeit concat4 ()

Результат виявився таким:

  • concat1: 153 наносекунди;
  • concat2: 275 наносекунд;
  • concat3: 398 наносекунд;
  • concat4: 393 наносекунди.

Тут ми можемо бачити, що concat1 (), який використовує оператор +, виконується набагато швидше за інших. Прикро, тому що мені дуже подобається str.format, проте тепер у задачах, які вимагають величезної кількості обробки рядків, від нього доведеться відмовитися.

Можливо, такі результати можуть бути пов’язані з тим, що короткі рядки не створюються в Python щоразу знову, а зберігаються в спеціальній таблиці? Давайте спробуємо змінити наші глобальні змінні таким чином:

x = 'abc' * 10000 y = 'def' * 10000

Тепер ми отримаємо наступні результати:

  • concat1: 2.64 мікросекунди;
  • concat2: 3.09 мікросекунди;
  • concat3: 3.33 мікросекунди;
  • concat4: 3.48 мікросекунди;

Так, кожен з методів тепер працював набагато довше, проте загальний результат не змінився – оператор + лідирує, як і раніше. Зазначимо так само, що різниця в часі між третім і четвертим методом, як і очікувалося, незначна.

Після цього я спробував не оголошувати змінні глобальними, а задавати їх в тілі методу, але на результати це все одно не вплинуло. Зрозуміло, можна проводити ще багато різних дослідів (наприклад, спробувати скласти більше, ніж два рядки), проте цього вже достатньо, щоб мати певне уявлення про швидкість роботи різних способів складання рядків у мові Python.

Переклад статті “Speedy string concatenation in Python”

Київ, Харків, Одеса, Дніпро, Запоріжжя, Кривий Ріг, Вінниця, Херсон, Черкаси, Житомир, Хмельницький, Чернівці, Рівне, Івано-Франківськ, Кременчук, Тернопіль, Луцьк, Ужгород, Кам'янець-Подільський, Стрий - за статистикою саме з цих міст програмісти найбільше переїжджають працювати до Львова. А Ви розглядаєте relocate?


Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *