Как мы все знаем, есть понимание списка, как
[i for i in [1, 2, 3, 4]]
и есть словарное понимание, как
{i:j for i, j in {1: 'a', 2: 'b'}.items()}
но
(i for i in (1, 2, 3))
окажется в генераторе, а не в tuple
понимании. Это почему?
Я предполагаю, что а tuple
является неизменным, но это не похоже на ответ.
{i:j for i,j in {1:'a', 2:'b'}}
должно быть{i:j for i,j in {1:'a', 2:'b'}.items()}
Ответы:
Вы можете использовать выражение генератора:
но скобки уже были приняты для ... выражений генератора.
источник
list(i for i in (1,2,3))
. Я действительно думаю, что это просто потому, что нет чистого синтаксиса для него (или, по крайней мере, никто не думал об этом)list(i for i in (1, 2, 3))
является выражением генератора, которое выводит список,set(i for i in (1, 2, 3))
выводит набор. Означает ли это, что синтаксис понимания не нужен? Возможно нет, но это очень удобно. В тех редких случаях вам нужен кортеж, вместо того, чтобы генерировать выражение генератора, он понятен и не требует изобретения другой скобки или скобки.[thing for thing in things]
создает список гораздо быстрее, чемlist(thing for thing in things)
. Понимание кортежей не будет бесполезным;tuple(thing for thing in things)
имеет проблемы с задержкой иtuple([thing for thing in things])
может иметь проблемы с памятью.A list or set or dict comprehension is just syntactic sugar to use a generator expression
? Это вызывает путаницу, когда люди видят в них эквивалентное средство для достижения цели. Технически это не синтаксический сахар, поскольку процессы на самом деле разные, даже если конечный продукт одинаков.Рэймонд Хеттингер (Raymond Hettinger) (один из разработчиков ядра Python) сказал следующее о кортежах в последнем твите :
Это (для меня) поддерживает идею, что если элементы в последовательности достаточно связаны, чтобы быть сгенерированным, ну, в общем, генератором, то это должен быть список. Хотя кортеж является итеративным и выглядит просто как неизменяемый список, на самом деле это Python-эквивалент структуры C:
становится в Python
источник
operator.itemgetter
в этом случае.tuple(obj[item] for item in items)
. В моем случае я включил это в понимание списка, чтобы составить список записей кортежей. Если мне нужно сделать это несколько раз по всему коду, то itemgetter выглядит великолепно. Возможно itemgetter был бы более идиоматическим в любом случае?Начиная с Python 3.5 , вы также можете использовать
*
синтаксис распаковки для распаковки выражения генератора:источник
tuple(list(x for x in range(10)))
( пути к коду идентичны , причем оба они строят alist
, с той лишь разницей, что последний шаг заключается в создании atuple
изlist
и выбрасыванииlist
когдаtuple
вывод необходимо). Означает, что вы на самом деле не избегаете пары временных.*(x for x in range(10))
не работает. Я получаюSyntaxError: can't use starred expression here
. Однакоtuple(x for x in range(10))
работает.Как
macm
упоминалось в другом постере , самый быстрый способ создать кортеж из генератора - этоtuple([generator])
.Сравнение производительности
Понимание списка:
Кортеж из списка понимания:
Кортеж из генератора:
Кортеж из распаковки:
Моя версия Python :
Поэтому вы всегда должны создавать кортеж из списка, если производительность не является проблемой.
источник
tuple
для listcomp требуется пиковое использование памяти на основе объединенного размера финалаtuple
иlist
.tuple
Из-за того, что genexpr медленнее, он означает, что вы платите только за финалtuple
, а не за временныйlist
(сам генxpr занимает примерно фиксированную память). Обычно не имеет смысла, но это может быть важно, когда размеры огромны.Понимание работает путем зацикливания или перебора элементов и назначения их в контейнер, а кортеж не может получать назначения.
После создания кортежа его нельзя добавлять, расширять или назначать. Единственный способ изменить кортеж - это если один из его объектов может быть назначен самому себе (это контейнер без кортежа). Потому что кортеж содержит только ссылку на этот тип объекта.
Также - у кортежа есть собственный конструктор,
tuple()
который вы можете предоставить любому итератору. Что означает, что для создания кортежа вы можете сделать:источник
lst = [x for x in ...]; x.append()
?Мое лучшее предположение, что они вышли за скобки и не думали, что это будет достаточно полезно, чтобы добавить "уродливый" синтаксис ...
источник
{*()}
, хотя и некрасиво, работает как пустой набор букв!set()
:){*[]}
строго уступает другим параметрам; пустая строка и emptytuple
, будучи неизменяемыми, являются синглетонами, поэтому для создания пустого не требуется никаких временныхset
. Напротив, пустоеlist
не является синглтоном, поэтому вам действительно нужно его сконструировать, использовать его для построенияset
, а затем уничтожить, теряя при этом любое тривиальное преимущество в производительности, которое дает одноглазый оператор обезьяны.Кортежи не могут быть эффективно добавлены в виде списка.
Таким образом, для понимания кортежа необходимо использовать внутренний список, а затем преобразовать его в кортеж.
Это было бы так же, как то, что вы делаете сейчас: tuple ([понимание])
источник
Круглые скобки не создают кортеж. иначе один = (два) не кортеж. Единственный выход - один = (два) или один = кортеж (два). Итак, решение:
источник
Я считаю, что это просто ради ясности, мы не хотим загромождать язык слишком многими различными символами. Кроме того,
tuple
понимание никогда не требуется , вместо этого можно использовать список с незначительными различиями в скорости, в отличие от точного понимания в отличие от понимания списка.источник
Мы можем генерировать кортежи из списка понимания. Следующий добавляет два числа последовательно в кортеж и дает список из чисел 0-9.
источник