Разница между 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 был новый синтаксис набора с самого начала, вероятно, пустой набор был бы определен с помощью {}
и пустым словарем с {:}
.