mirror of
https://github.com/satwikkansal/wtfpython
synced 2024-11-21 10:44:21 +01:00
Translate Let's make a giant string! example
This commit is contained in:
parent
ebe5f59a9d
commit
00e420fc51
99
translations/README-ru.md
vendored
99
translations/README-ru.md
vendored
@ -3430,6 +3430,103 @@ def square(x):
|
||||
```
|
||||
|
||||
#### 💡 Объяснение:
|
||||
+ Операнд `+=` быстре `+` для "сложения" 2 и более строк, так как первая строка (например, `s1` for `s1 += s2 + s3`) не уничтожается во время формирования финальной строки.
|
||||
+ Операнд `+=` быстрее `+` для "сложения" 2 и более строк, так как первая строка (например, `s1` for `s1 += s2 + s3`) не уничтожается во время формирования финальной строки.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### ▶ Сделаем гигантскую строку!
|
||||
<!-- Example ID: c7a07424-63fe-4504-9842-8f3d334f28fc --->
|
||||
```py
|
||||
def add_string_with_plus(iters):
|
||||
s = ""
|
||||
for i in range(iters):
|
||||
s += "xyz"
|
||||
assert len(s) == 3*iters
|
||||
|
||||
def add_bytes_with_plus(iters):
|
||||
s = b""
|
||||
for i in range(iters):
|
||||
s += b"xyz"
|
||||
assert len(s) == 3*iters
|
||||
|
||||
def add_string_with_format(iters):
|
||||
fs = "{}"*iters
|
||||
s = fs.format(*(["xyz"]*iters))
|
||||
assert len(s) == 3*iters
|
||||
|
||||
def add_string_with_join(iters):
|
||||
l = []
|
||||
for i in range(iters):
|
||||
l.append("xyz")
|
||||
s = "".join(l)
|
||||
assert len(s) == 3*iters
|
||||
|
||||
def convert_list_to_string(l, iters):
|
||||
s = "".join(l)
|
||||
assert len(s) == 3*iters
|
||||
```
|
||||
|
||||
**Результат:**
|
||||
|
||||
```py
|
||||
# Фрагменты выполняются в оболочке `ipython` с использованием `%timeit` для лучшей читаемости результатов.
|
||||
# Вы также можете использовать модуль timeit в обычной оболочке python shell/scriptm=, пример использования ниже
|
||||
# timeit.timeit('add_string_with_plus(10000)', number=1000, globals=globals())
|
||||
|
||||
>>> NUM_ITERS = 1000
|
||||
>>> %timeit -n1000 add_string_with_plus(NUM_ITERS)
|
||||
124 µs ± 4.73 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
|
||||
>>> %timeit -n1000 add_bytes_with_plus(NUM_ITERS)
|
||||
211 µs ± 10.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
|
||||
>>> %timeit -n1000 add_string_with_format(NUM_ITERS)
|
||||
61 µs ± 2.18 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
|
||||
>>> %timeit -n1000 add_string_with_join(NUM_ITERS)
|
||||
117 µs ± 3.21 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
|
||||
>>> l = ["xyz"]*NUM_ITERS
|
||||
>>> %timeit -n1000 convert_list_to_string(l, NUM_ITERS)
|
||||
10.1 µs ± 1.06 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
|
||||
```
|
||||
|
||||
Увеличим число итераций в 10 раз.
|
||||
|
||||
```py
|
||||
>>> NUM_ITERS = 10000
|
||||
>>> %timeit -n1000 add_string_with_plus(NUM_ITERS) # Линейное увеличение времени выполнения
|
||||
1.26 ms ± 76.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
|
||||
>>> %timeit -n1000 add_bytes_with_plus(NUM_ITERS) # Квадратичное увеличение
|
||||
6.82 ms ± 134 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
|
||||
>>> %timeit -n1000 add_string_with_format(NUM_ITERS) # Линейное увеличение
|
||||
645 µs ± 24.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
|
||||
>>> %timeit -n1000 add_string_with_join(NUM_ITERS) # Линейное увеличение
|
||||
1.17 ms ± 7.25 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
|
||||
>>> l = ["xyz"]*NUM_ITERS
|
||||
>>> %timeit -n1000 convert_list_to_string(l, NUM_ITERS) # Линейное увеличение
|
||||
86.3 µs ± 2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
|
||||
```
|
||||
|
||||
#### 💡 Объяснение
|
||||
|
||||
- Подробнее о [timeit](https://docs.python.org/3/library/timeit.html) или [%timeit](https://ipython.org/ipython-doc/dev/interactive/magics.html#magic-timeit) вы можете прочитать по этим ссылкам. Они используются для измерения времени выполнения фрагментов кода.
|
||||
- Не используйте `+` для генерации длинных строк - В Python `str` неизменяема, поэтому левая и правая строки должны быть скопированы в новую строку для каждой пары конкатенаций. Если вы конкатенируете четыре строки длины 10, то вместо 40 символов вы скопируете (10+10) + ((10+10)+10) + (((10+10)+10)+10) = 90 символов. С увеличением количества и размера строки ситуация ухудшается в квадратичной прогрессии (что подтверждается временем выполнения функции `add_bytes_with_plus`).
|
||||
- Поэтому рекомендуется использовать синтаксис `.format.` или `%` (правда, для очень коротких строк они немного медленнее, чем `+`).
|
||||
- Или лучше, если у вас уже есть содержимое в виде итерируемого объекта, тогда используйте `''.join(iterable_object)`, что гораздо быстрее.
|
||||
- В отличие от `add_bytes_with_plus` из-за оптимизаций `+=`, рассмотренных в предыдущем примере, `add_string_with_plus` не показало квадратичного увеличения времени выполнения. Если бы оператор был `s = s + "x" + "y" + "z"` вместо `s += "xyz"`, увеличение было бы квадратичным.
|
||||
```py
|
||||
def add_string_with_plus(iters):
|
||||
s = ""
|
||||
for i in range(iters):
|
||||
s = s + "x" + "y" + "z"
|
||||
assert len(s) == 3*iters
|
||||
|
||||
>>> %timeit -n100 add_string_with_plus(1000)
|
||||
388 µs ± 22.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
|
||||
>>> %timeit -n100 add_string_with_plus(10000) # Quadratic increase in execution time
|
||||
9 ms ± 298 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
|
||||
```
|
||||
|
||||
- Такое число способов форматирования и создания гигантской строки несколько противоречит [Zen of Python](https://www.python.org/dev/peps/pep-0020/), согласно которому,
|
||||
|
||||
> должен быть один - и желательно только один - очевидный способ сделать это.
|
||||
|
||||
---
|
||||
|
Loading…
Reference in New Issue
Block a user