Разница между dict и set (python)

Итак, я знаю, что это,

a = {}  # dict

Создает пустой словарь. Теперь я также понял, что это,

b = {1, 2, 3}  # set

Создает набор. Это легко проверить, так как

>>>print(type(a))
<class 'dict'>

>>>print(type(b))
<class 'set'>

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

Может ли кто-нибудь объяснить мне, почему мы делаем это таким образом? Это по историческим причинам, или я пропущу что-то явно очевидное?

Ответы

Ответ 1

В Python 2 не было заданных литералов, исторически фигурные скобки использовались только для словарей. Наборы могут быть получены из списков (или любых итераций):

set([1, 2, 3])
set([i for i in range(1, 3)])

Python 3 представил набор литералов и понимания (см. PEP-3100), что позволило нам избежать промежуточных списков:

{1, 2, 3}
{i for i in range(1, 3)}

Однако пустая форма набора была зарезервирована для словарей из-за обратной совместимости. Ссылки из [Python-3000] наборов в P3K? состояния:

Я уверен, что мы можем что-то решить - я согласен, {} для пустого набора и {:} для пустого dict были бы идеальными, если бы не обратная совместимость. Мне понравилась идея "специального пустого объекта", когда я впервые написал PEP (то есть, {} должен был быть чем-то, что могло бы превратиться либо в набор, либо в диктовку), но один из преподавателей убедил меня, что это приведет к путанице в умы новичков (а также боль в реализации).

Следующее сообщение описывает эти правила лучше:

Я думаю, что у Гвидо было лучшее решение. Используйте set() для пустых наборов, используйте {} для пустых диктовок, используйте {genexp} для набора пониманий/отображений, используйте {1,2,3} для явных литералов набора и используйте {k1:v1, k2:v2} для в буквальном смысле слова. Мы всегда можем добавить {/} позже, если спрос превышает отвращение.

Ответ 2

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

>>> {'foo': 'bar'}
{'foo': 'bar'}
>>> type(_)
<type 'dict'>

Позднее к языку были добавлены наборы, а в фигурной скобке {..} указаны только элементы, а не пары:

>>> {'foo'}
set(['foo'])
>>> type(_)
<type 'set'>

Обратите внимание, что в Python 2 интерпретатор отображает объект с помощью функции set(). Это также, как вы указываете пустой набор:

>>> emptyset = set()

В Python 3 более новая нотация {..} используется при отображении объекта, если только он не пуст:

>>> {'foo'}
{'foo'}
>>> _ - {'foo'}  # difference, removing the one element
set()

Тип set() был добавлен к языку Python в версии 2.4 (см. PEP 218), синтаксис фигурных скобок для литералов набора был добавлен в Python 3 и перенесен в Python 2.7.

Ответ 3

Тот факт, что {} используется для пустого словаря, а не для пустого набора, имеет в основном исторические причины. Синтаксис {'a': 100, 'b': 200} для словарей был примерно с самого начала Python. Синтаксис {1, 2, 3} для наборов был введен с Python 2.7. Поскольку {} был использован в течение такого длительного времени, он останется как способ определения пустого словаря. Если бы у Python был новый синтаксис набора с самого начала, вероятно, пустой набор был бы определен с помощью {} и пустым словарем с {:}.