он resizes array несколько раз (при достаточном кол-ве элементов для тригерра) как при вызывании метода .append(), или же он сразу выделяет память на все элементы?
ну он не может сразу узнать сколько элементов будет
почему? Обычно же в результате list comprehension выходит то же кол-во элементов, что и в начале (при условии отсутствия if)
Допустим, ты делаешь список из генератора, сколько в нем будет элементов?
Ну питон не может в общем случае знать сколько элементов итератор вернёт
в каком начале?
items = [1, 2, 3, 4, 5] doubled_items = [i*2 for i in items] Разве в этом случае он не может знать длину первого списка?
a = (1 for _ in range(10)) b = itertools.chain(a,a) c = [x for x in b]
Я же и не говорю, что он всегда будет знать - но в описаном мною случае он может узнать длину первоначального списка за О(1), так ведь? Но я понял, в моем случае лучше использовать linked list, спасибо
что? при чем тут linked list? что ты хочешь сделать?
А если там будет if?
У меня есть длинный список обьектов, в JSON формате (примерно): [{‘company_id’: 1, ‘module_name’: ‘abcde’, …}, {‘company_id’: 1, …}, {‘company_id’: 2, …}, {‘company_id’: 3, …}] Мне нужно эти обьекты сгрупировать по company_id и вернуть словарь где company_id будет ключ, а value будет любая iterable. Кстати, у меня список сортирован по company_id. Что насчет .slice()? Он тоже ресайзит список несколько раз, или он сразу выделяет нужное кол-во слотов памяти?
itertools.groupby
Если там будет if, то интерпретатор будет знать, что там if, нет?
Ну т.е. ты хочешь оптимизацию чисто для кейса [x*x for x in list], и все?
Спасибо. А если бы этой функции не существовало, просто ради понимания, linked list было бы правильно в этом случае использовать?
не вижу смысла в linkedlist тут. С непрерывной памятью работать проще.
А этого мало? Если у меня в списке миллион элементов, это немаленький прирост даст
А в for x in list: result.append(x*x) не даст
Это повод не оптимизировать один из двух use cases? Лист компрехеншн и так быстрее работает чем for loop, что в этом плохого?
https://peps.python.org/pep-0424/#rationale https://www.pythoninsight.com/2018/08/length-hints-in-python/ Но именно в comprehension не используется, похоже
у нас в расте итератор выдаёт верхнюю и нижнюю границу
В расте итераторы разве не другое означают, что в питоне?
как плюсы? в виде фиктивного объекта?
я не понимаю твои волшебные слова
мне кажется когда ты пишешь про раст у него такое же
ну там верхняя граница - это специальный объект, который нихрена не говорит о том, сколько там реально объектов
да нет, просто tuple[int, int | None], если по-питоновски https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.size_hint
https://discuss.python.org/t/simple-generators-should-have-len-or-length-hint-when-possible/18729/4
а как сделать бесконечный итератор?
тогда верхний баунд None
а как сделать итератор по данным, которые мы на ходу генерируем и не знаем сколько будет?
ну хинт это другое, это как если проверить __len__ у итератора, если есть, то вызвать и на него ориентироваться
ну то есть только в тривиальных случаях будет не None
ну по умолчанию хинт (0, None) но можно его переопределить для своего итератора неправильный хинт не может привести к нарушению memory safety, просто код, использующий хинты, может работать неоптимально
если ты реализуешь итератор по своей коллекции ты знаешь длину
такой код в расте бы даже не скомпилировался кстати
chain требует владения обоими аргументами получить два владения над одним объектом в расте нельзя
А, ты из-за мутабельности
в питоне из-за таких приколов получается в итоге итератор из десяти элементов (хотя у обоих аргументов по десять элементов)
Нет, у обоих аргуметов неизвестное число элементов
так у тебя repeat, а тут генераторное выражение
давай ашдеук
ну он просто максимум вернул
оно, кстати, выдыхается на первой итерации, я чет думал, что два раза повторится
какой то претти принт у вас не очень претти
Не вижу здесь принта
макрос dbg! претти-принтит аргумент и возвращает его можно внутри выражения его вставить и увидеть значение какой-то части выражения, при этом не ломая код примерно def dbg[T](x: T) -> T: print(repr(x)) return x
По-моему в питоне лист — это буквально лист. Ну, то есть, связный список, поддерживающий индексацию, а не типизированный массив. Поэтому ты любой объект туда засунуть и можешь
нет, это не связный список
https://docs.python.org/3/glossary.html#term-list
«...больше похож на массив, чем на связанный список, поскольку доступ к элементам осуществляется за О(1)» — связный список с поддержкой индексов
Там нет ссылки на следующий элемент и реализован он как массив
https://github.com/python/cpython/blob/7f963bfc79a515dc9822ebddbfb1b5927d2dda09/Objects/listobject.c#L279-L305 похоже на связный список?
Как тогда выделяется память под новый элемент? Допустим, один объект в списке — строка, другой — экземпляр класса с кучей вложенностей и данных, третий — int8, потом флоат, ещё дабл...
можешь считать это std::vector<PyObject*>
Точно также как работают динамические массивы чего угодно где угодно. Хранятся указатели
в частности 301-302 строки у связного списка не так реализуется вставка в произвольное место
Память выделяется не под элемент. Память выделяется с запасом как и в любой другой реализации вектора
Обсуждают сегодня