Почему {} работает с целым числом, а set() — нет?

Когда я набираю {5} в консоли, я получаю набор:

>>> {3}
{3}

Принимая во внимание, что set(5) приводит к ошибке:

>>> set(5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable

{} или функцию set() можно использовать для создания наборов.. Так почему это происходит?

задавать принимает итерируемый объект, например список, а не целое число.
Devesh Kumar Singh 12.06.2019 16:49

По той же причине [3] и list(3) не одно и то же.

chepner 12.06.2019 16:50

Что вы подразумеваете под "почему"? Вы спрашиваете о преимущество{}синтаксис, о разница базовых конструкций или о чем-то еще?

MisterMiyagi 12.06.2019 16:57

@MisterMiyagi Из ответа я понял, почему set (5) не работает, но почему тогда {5} работает?

Snow 12.06.2019 16:59

Из документов: docs.python.org/3/tutorial/datastructures.html#setsNote: to create an empty set you have to use set(), not {}; the latter creates an empty dictionary

Devesh Kumar Singh 12.06.2019 17:01

@DeveshKumarSingh Это для пустого набора. type({5}) это <class 'set'>

Snow 12.06.2019 17:01

@Snow {5} не является вызовом функции; это набор буквальный, точно так же, как 5 является литералом int.

chepner 12.06.2019 17:06
setмог были написаны так, чтобы принимать произвольное количество аргументов, так что set(1,2,3) == {1,2,3} и set(5) == {5}, но тогда вы сталкиваетесь с проблемой наборов итераций. Хотя set("ab", "cd") явно будет {"ab", "cd"}, каким должно быть set("ab")? Это один набор со строкой из двух букв или набор из двух элементов строк из одной буквы?
chepner 12.06.2019 17:08
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
8
67
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Поскольку определение set это:

class set([iterable])

Он не принимает отдельные значения, он принимает итерируемые значения один. Например.:

set([5, 6, 7])

Вы бы использовали литерал, когда жестко кодируете фиксированное количество значений или переменных:

{'foo', bar, baz()}

И вы бы использовали конструктор set, когда у вас есть итерация один, которую вы хотите «распаковать» в набор:

set(baz)
set(foo(bar) for bar in baz)
set(map(foo, baz))

«k» также является отдельным значением, но set('k') приводит к набору. Вы имеете в виду числовые типы данных?

Snow 12.06.2019 17:08

@Snow [5,6,7] — это также одно индивидуальное значение, но это итерируемое значение. 'k' — это также итерируемое значение, которое (как ни странно) содержит ровно одну строку, 'k'. (Строки в Python выглядят странно из-за отсутствия отдельного типа char.)

chepner 12.06.2019 17:10

Строки повторяемый. set('foo') результаты в сете {'f', 'o'}.

deceze 12.06.2019 17:10

@chepner deceze Понял. Спасибо!

Snow 12.06.2019 17:12

Когда вы определяете экземпляр набора для нескольких значений, значения не обязательно являются конкретными. Например, они могут быть лениво вычислены генератором:

values = (a%1 for a in range(2500000))
my_set1 = set(values)  # values can be *any* iterable type

Это эффективно с точки зрения использования памяти, так как set всегда содержит не более двух значений. Дубликаты удаляются по мере их появления.

Если бы set принимал отдельные значения, вам пришлось бы *-распаковывать ленивую итерацию во временный кортеж. Промежуточный кортеж будет содержать все 2500000 значений.

def inefficient_set(*items):  # items is an intermediate tuple
    return set(items)

values = (a%1 for a in range(2500000))
my_set2 = inefficient_set(*values)

Когда set принимает итерируемый объект, вы используете промежуточный контейнер только тогда, когда он вам нужен.


Когда вы определяете буквальный набор из нескольких значений, все значения уже являются конкретными. Точно так же, когда вы определяете буквальный набор ленивых значений, они также являются конкретными.

my_set3 = {0, 1, 0, 1, 0, 1}            # values are known to be concrete
my_set4 = {a%1 for a in range(2500000)} # values are known to be lazy

В этом случае для повторяемый потребуется бесполезный промежуточный контейнер. Когда {} принимает отдельные значения, вы используете промежуточный контейнер только тогда, когда он вам нужен.


Важно учитывать, что {...} — это синтаксис, тогда как set(...) — это обычный создание экземпляра типа. В Python синтаксис статичен, тогда как типы являются динамическими. Это позволяет статически отличать {a, b, c, ...} литералы конкретных значений от {... for ... in ...} вкраплений.

Это не очень актуально. Это бонус, который set может отбрасывать дубликаты при чтении их из ленивой итерации, но вы также можете написать set([0,1,0,1,0,1]) и получить набор из двух элементов.

chepner 12.06.2019 17:16

Обратите внимание, что вы могли бы и написали понимание множества… {a%1 for a in range(2500000)}

deceze 12.06.2019 17:16

@chepner Дело в том, что, когда set и {} работают таким образом, вы могу используете оптимальный путь, но можете этого не делать. Если бы они работали по-другому, вы не могли бы использовать оптимальный путь.

MisterMiyagi 12.06.2019 17:18

@deceze будет ли временная сложность понимания такой же, как set((a%1 for a in range(2500000)))? Или ниже?

Snow 12.06.2019 17:28

@deceze Я выбрал выражение генератора только для демонстрации. Дело в том, что аргумент set может быть любого типа, тогда как тип аргумента {..} статически определяется синтаксисом.

MisterMiyagi 12.06.2019 18:09

@Snow Сложность одинакова в любом случае, и практически оба делают одно и то же за кулисами - подают генератор в конструктор набора. В принципе, set может быть переопределен в вашем случае. Обратите внимание, что pypy может оптимизировать литерал {} примерно вдвое быстрее, чем использование set.

MisterMiyagi 12.06.2019 18:15

Другие вопросы по теме