2015-10-20 2 views
-5

я прочитал один article:Если питон набор не позволяет изменяемый объект, то почему это позволяет добавить список с одним элементом

«Наборы реализованы таким образом, что не позволяет изменяемые объекты»

Когда я выполняю:

cities = set((["Python","Perl"], ["Paris", "Berlin", "London"])) 

Он бросает ошибку:

TypeError: list objects are unhashable

Я искал эту ошибку и понимал, что набор не разрешает изменчивые объекты, следовательно, это вызывает эту ошибку. Но поскольку вы можете видеть, что элемент внутри набора является кортежем, который является неизменным, поэтому он должен его допускать. проверил с type() Но когда я попытался:

cities = set((["Python","Perl"])) 

Он работал, даже если элемент внутри набора является изменяемым список. Я действительно смущен. Теперь я смущен. :-(

+0

Попробуйте проверить тип элементов множества. – juanchopanza

ответ

1

он работал, даже если элемент внутри набора является изменяемым список

Вы инициализирует набор с одним аргументом (["Python","Perl"]), который является таким же, как ["Python","Perl"], то есть список строк .

набор распаковывает этот список, оставив ее с двумя элементами типа str:

>>> cities = set((["Python","Perl"])) 
>>> for c in cities: print type(c), c 
<type 'str'> Python 
<type 'str'> Perl 
0

Прежде всего, хешируемые и неизменные - не одно и то же. python glossary содержит определение hashable:

Объект является hashable, если он имеет значение хеш-функции, которые никогда не изменяется в течение его срока службы (требуется метод с хэш()), и их можно сравнить с другими объектами (ему необходим метод экв() или cmp()). Объекты Hashable, которые сравнивают одинаковые, должны иметь одно и то же значение хэш-функции.

Hashability делает объект пригодным для использования в качестве словарного ключа и набора элементов, поскольку эти структуры данных используют значение хэш внутри.

Все неизменные встроенные объекты Python являются хешируемыми, в то время как нет изменяемых контейнеров (таких как списки или словари). Объекты, являющиеся экземплярами пользовательских классов, по умолчанию хешируются; все они сравниваются неравномерно (за исключением самих себя), а их хэш-значение - их id().

Как вы можете видеть, любой объект, который реализует __hash__, __eq__ и __cmp__ может быть добавлен к набору. Мудрость реализации этих методов для сильно изменяемых объектов, таких как списки, вызывает сомнения, но это можно сделать. Неизменяемость ни в коем случае не является обязательным требованием.

Во-вторых, набор может быть инициализирован из списка, если каждый из элементов хешируется.Линия cities = set((["Python","Perl"])) строит набор с Python и Perl как элементы. Обратите внимание, что дополнительные круглые скобки не создают кортеж. Добавив дополнительную запятую, cities = set((["Python","Perl"],)) даст вам ту же ошибку, что и раньше, так как теперь у вас будет кортеж. В этом случае кортеж пытается вычислить хэш, но его хэш зависит от хэшей списков, которых не существует.

0

Если вы хотите кортеж кортежей в вашем примере вы должны попробовать:

cities = set((("Python","Perl"), ("Paris", "Berlin", "London"))) 
print cities #Output set([('Paris', 'Berlin', 'London'), ('Python', 'Perl')]) 
type(cities) #Output <type 'set'> 
Смежные вопросы