Skip to content

Commit 00e420f

Browse files
committed
Translate Let's make a giant string! example
1 parent ebe5f59 commit 00e420f

File tree

1 file changed

+98
-1
lines changed

1 file changed

+98
-1
lines changed

translations/README-ru.md

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3430,6 +3430,103 @@ def square(x):
34303430
```
34313431
34323432
#### 💡 Объяснение:
3433-
+ Операнд `+=` быстре `+` для "сложения" 2 и более строк, так как первая строка (например, `s1` for `s1 += s2 + s3`) не уничтожается во время формирования финальной строки.
3433+
+ Операнд `+=` быстрее `+` для "сложения" 2 и более строк, так как первая строка (например, `s1` for `s1 += s2 + s3`) не уничтожается во время формирования финальной строки.
3434+
3435+
---
3436+
3437+
3438+
### ▶ Сделаем гигантскую строку!
3439+
<!-- Example ID: c7a07424-63fe-4504-9842-8f3d334f28fc --->
3440+
```py
3441+
def add_string_with_plus(iters):
3442+
s = ""
3443+
for i in range(iters):
3444+
s += "xyz"
3445+
assert len(s) == 3*iters
3446+
3447+
def add_bytes_with_plus(iters):
3448+
s = b""
3449+
for i in range(iters):
3450+
s += b"xyz"
3451+
assert len(s) == 3*iters
3452+
3453+
def add_string_with_format(iters):
3454+
fs = "{}"*iters
3455+
s = fs.format(*(["xyz"]*iters))
3456+
assert len(s) == 3*iters
3457+
3458+
def add_string_with_join(iters):
3459+
l = []
3460+
for i in range(iters):
3461+
l.append("xyz")
3462+
s = "".join(l)
3463+
assert len(s) == 3*iters
3464+
3465+
def convert_list_to_string(l, iters):
3466+
s = "".join(l)
3467+
assert len(s) == 3*iters
3468+
```
3469+
3470+
**Результат:**
3471+
3472+
```py
3473+
# Фрагменты выполняются в оболочке `ipython` с использованием `%timeit` для лучшей читаемости результатов.
3474+
# Вы также можете использовать модуль timeit в обычной оболочке python shell/scriptm=, пример использования ниже
3475+
# timeit.timeit('add_string_with_plus(10000)', number=1000, globals=globals())
3476+
3477+
>>> NUM_ITERS = 1000
3478+
>>> %timeit -n1000 add_string_with_plus(NUM_ITERS)
3479+
124 µs ± 4.73 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
3480+
>>> %timeit -n1000 add_bytes_with_plus(NUM_ITERS)
3481+
211 µs ± 10.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
3482+
>>> %timeit -n1000 add_string_with_format(NUM_ITERS)
3483+
61 µs ± 2.18 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
3484+
>>> %timeit -n1000 add_string_with_join(NUM_ITERS)
3485+
117 µs ± 3.21 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
3486+
>>> l = ["xyz"]*NUM_ITERS
3487+
>>> %timeit -n1000 convert_list_to_string(l, NUM_ITERS)
3488+
10.1 µs ± 1.06 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
3489+
```
3490+
3491+
Увеличим число итераций в 10 раз.
3492+
3493+
```py
3494+
>>> NUM_ITERS = 10000
3495+
>>> %timeit -n1000 add_string_with_plus(NUM_ITERS) # Линейное увеличение времени выполнения
3496+
1.26 ms ± 76.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
3497+
>>> %timeit -n1000 add_bytes_with_plus(NUM_ITERS) # Квадратичное увеличение
3498+
6.82 ms ± 134 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
3499+
>>> %timeit -n1000 add_string_with_format(NUM_ITERS) # Линейное увеличение
3500+
645 µs ± 24.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
3501+
>>> %timeit -n1000 add_string_with_join(NUM_ITERS) # Линейное увеличение
3502+
1.17 ms ± 7.25 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
3503+
>>> l = ["xyz"]*NUM_ITERS
3504+
>>> %timeit -n1000 convert_list_to_string(l, NUM_ITERS) # Линейное увеличение
3505+
86.3 µs ± 2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
3506+
```
3507+
3508+
#### 💡 Объяснение
3509+
3510+
- Подробнее о [timeit](https://docs.python.org/3/library/timeit.html) или [%timeit](https://ipython.org/ipython-doc/dev/interactive/magics.html#magic-timeit) вы можете прочитать по этим ссылкам. Они используются для измерения времени выполнения фрагментов кода.
3511+
- Не используйте `+` для генерации длинных строк - В Python `str` неизменяема, поэтому левая и правая строки должны быть скопированы в новую строку для каждой пары конкатенаций. Если вы конкатенируете четыре строки длины 10, то вместо 40 символов вы скопируете (10+10) + ((10+10)+10) + (((10+10)+10)+10) = 90 символов. С увеличением количества и размера строки ситуация ухудшается в квадратичной прогрессии (что подтверждается временем выполнения функции `add_bytes_with_plus`).
3512+
- Поэтому рекомендуется использовать синтаксис `.format.` или `%` (правда, для очень коротких строк они немного медленнее, чем `+`).
3513+
- Или лучше, если у вас уже есть содержимое в виде итерируемого объекта, тогда используйте `''.join(iterable_object)`, что гораздо быстрее.
3514+
- В отличие от `add_bytes_with_plus` из-за оптимизаций `+=`, рассмотренных в предыдущем примере, `add_string_with_plus` не показало квадратичного увеличения времени выполнения. Если бы оператор был `s = s + "x" + "y" + "z"` вместо `s += "xyz"`, увеличение было бы квадратичным.
3515+
```py
3516+
def add_string_with_plus(iters):
3517+
s = ""
3518+
for i in range(iters):
3519+
s = s + "x" + "y" + "z"
3520+
assert len(s) == 3*iters
3521+
3522+
>>> %timeit -n100 add_string_with_plus(1000)
3523+
388 µs ± 22.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
3524+
>>> %timeit -n100 add_string_with_plus(10000) # Quadratic increase in execution time
3525+
9 ms ± 298 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
3526+
```
3527+
3528+
- Такое число способов форматирования и создания гигантской строки несколько противоречит [Zen of Python](https://www.python.org/dev/peps/pep-0020/), согласно которому,
3529+
3530+
> должен быть один - и желательно только один - очевидный способ сделать это.
34343531
34353532
---

0 commit comments

Comments
 (0)