Comments 33
На картинке “dictionsry”. Вы б хоть хотя бы такую элементарищину вычитывали бы… «статья» - хлам, конечно. Если уж вы про базовые вещи, то хотя бы про память бы чтоль рассказали, как оно там внутри все хранится и для чего нужны словари, и когда кортежи лучше списков (и наоборот).
Благодарим за ваши комментарии! Про опечатку передадим редактору, про память расскажем в новых статьях.
О, а я в надписи "изображение (dictionsry)" возмутился на "изображение" (в данном случае projection - "отображение") а `s` не заметил.
Годы идут, но ничего не меняется
Термин "последовательности" слишком математический. С точки зрения программирования привычнее было бы говорить о "массивах", наверное.
Ну, во встроенном модуле typing обобщённый тип для них называется Sequence, что означает именно "последовательность", как в математическом, так и в повседневном смысле.
привычнее было бы говорить о "массивах"
"Привычнее" - понятие субъективное, но в целом термин "последовательность" в программировании вполне устоявшийся.
Кроме того, "массив" в питоне - это отдельный тип данных.
Ну, насчёт массивов в Питоне (и не только в нём) - там прям по той формуле "you need to go deeper". На разных слоях вещи выглядят по-разному. На верхнем уровне их как будто и нет встроенных, но если начать копаться, то тот же список - это на самом то деле динамический массив. Это и в Питоне так и, например, в C# так же сделано.
Мда... Даже про лимиты числовых данных ничего не сказано.
В отличие от строк и кортежей, список можно изменить.
Вот прочитает новичок и подумает, что строки нельзя менять. Один раз присвоил им значения и всё - до конца работы программы не изменить. Тоже самое подумает про числа, после первой картинки.
Но ведь нельзя же строки менять.
А чем переназначение от смены отличается?
Сравните время исполнения:
b = bytearray()
for i in range(1_000_000):
b += b'b'
s = str()
for i in range(1_000_000):
s += 's'В первом случае изменяется переменная, во втором случае каждый раз создается новая.
А вот и нет. Я сам в своё время был в шоке, но операция += для строк в питоне оптимизирована. Место под строку видимо выделяется с запасом, примерно как под список. И если посмотреть через dis, то для += используется операция INPLACE_ADD вместо BINARY_ADD для обычного сложения. Добавление в строку всего в 2 раза медленнее, чем добавление в байтовый массив. Но если заменить += на реальное сложение строк с промежуточной записью в другую переменную, то работать такая функция будет уже в 500 раз медленнее. Замена на s = s + 's', кстати, не помогает - всё-равно работает быстро. Питон понимает, что его хотят обмануть и всё-равно на каком-то этапе меняет этот код на s += 's'.
s = str()
id_s = id(s)
prev_i = 0
for i in range(1_000_000):
s += 's'
if id_s != id(s):
print (i, i - prev_i, id_s, id(s))
prev_i = i
id_s = id(s)Можно увидеть что id меняется не на каждой итерации, видать каждый раз когда выполняется новая аллокация.
Да, id меняется, но сама операция выполняется быстро, вы замерьте время. Я предполагаю, что питоновский объект меняется, но сама строка в памяти лежит на том же месте и не копируется, а дописывается.
Запустил:
0 0 4382700472 4382744632
1 1 4382744632 4370906112
2 1 4370906112 4370906256
3 1 4370906256 4370906352
4 1 4370906352 4370906448
5 1 4370906448 4370906544
6 1 4370906544 4370906640
7 1 4370906640 4371180656
8 1 4371180656 4371180464
9 1 4371180464 4371180336
Каждая итерация новый id.
Python 3.13.1
У меня немного по другому (3.13.1)
[2025-01-29 16:15:08] [D:\Sources\_pythonish\locals] [ 3.13.1] [ .313][ 0.136]
➜ python .\x.py
0 0 140717673633472 140717673677632
1 1 140717673677632 2090190649600
7 6 2090190649600 2090190787696
23 16 2090190787696 2090190982720
39 16 2090190982720 2090188633264
55 16 2090188633264 2090190497568
71 16 2090190497568 2090190352176
87 16 2090190352176 2090188058768
103 16 2090188058768 2090190800336
119 16 2090190800336 2090188042848Проверил с разными версиями питона, и такое поведение вижу на 3.8, 3.9 и 3.10, а 3.11, 3.12 и 3.13 уже выделяют новый id после каждой новой итерации
❯ cat t.py
from time import time
b = bytearray()
t = time()
for i in range(1_000_000):
b += b'b'
print(time() - t)
s = str()
t = time()
for i in range(1_000_000):
s += 's'
print(time() - t)
❯ python3.8 t.py
0.06453704833984375
0.12097501754760742
❯ python3.9 t.py
0.050421953201293945
0.10408806800842285
❯ python3.10 t.py
0.04788088798522949
0.09204506874084473
❯ python3.11 t.py
0.05541682243347168
10.259689092636108
❯ python3.12 t.py
0.0602419376373291
9.597757816314697
❯ python3.13 t.py
0.07121491432189941
10.046982049942017Совпадает с вашим предыдущим ответом, кстати.
https://stackoverflow.com/questions/74605279/python-3-11-worse-optimized-than-3-10
It turns out that the generated bytecode is different between the two version and it is the root of the performance issue. Indeed, CPython 3.10 generates an
INPLACE_ADDbytecode instruction while CPython 3.11 generates aBINARY_OPbytecode instruction.
У меня на компе первый цикл выполняется за 0.06 сек, второй за 9.5 сек
Так что разница по скорости не в два раза
a = ['a','a','a']
b = "aaa"
for i in range(3):
a[i] = a[i].upper() # да
b[i] = b[i].upper() # нет
Наверное тем что строки имутабельные и после создания их содержимое менять нельзя. Но конечно можно создать новую - но это разные вещи. Вам ниже уже об этом написали.
Вот. Только где об этом хоть слово в статье? Если авторы дают термин изменяемости, то надо объяснить, что это. Иначе это больше звучит так, будто это аналог констант из других языков.
Вы путаете возможность изменения объектов (мутабельность) с возможностью присвоить что-то в переменную. В питоновскую переменную можно присвоить что угодно по ходу работы программы, но это свойство переменных как ярлычков/ссылок, а не свойство объектов, на которые эти переменные указывают.
Кстати, строки в питоне не совсем иммутабельны, я там ниже комментирую эту тему.
Я не путаю. Я говорю, что статья не даёт даже базовых знаний о типах данных.
Спасибо за ваши комментарии! Обратная связь от читателей помогает нам совершенствовать контент. Если вам не сложно - вы могли бы дать ссылки на статьи, которые, на ваш взгляд, в полном объеме дают базовые знания?
Удивительно, но вот - Built-in Types
а как насчет всем, кто вам дельные вещи посоветовал, просто взять и оплатить время исходя из рабочего дня вашего редактора? А, ну да, можно еще и того, кто сюда посты пишет. Вот это дешевое "спасибо за комментарии" - кажется, что неискреннее процентов на 100.
А AVL-дерево как на питоне построить? Где указатели?
Типы данных в Python для самых маленьких