Understanding Python Set Behavior

The documentation for the built-in set type states:

 class set([iterable]) 

Returns a new set or frozenset object whose elements are taken from the iteration. Set elements must be hashed.

Everything is fine, but why does it work:

 >>> l = range(10) >>> s = set(l) >>> s set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) 

And this is not so:

  >>> s.add([10]) Traceback (most recent call last): File "<pyshell#7>", line 1, in <module> s.add([10]) TypeError: unhashable type: 'list' 

Both are lists. Is some kind of magic happening during initialization?

+4
source share
6 answers

When you initialize the set, you provide a list of values ​​that should be hashed.

 s = set() s.add([10]) 

coincides with

 s = set([[10]]) 

which produces the same error that you see right now.

+11
source

In this line:

 s.add([10]) 

You are trying to add a list to a set, not to list items. If you want to add list items, use the update method.

+5
source
 In [13]: (2).__hash__ Out[13]: <method-wrapper '__hash__' of int object at 0x9f61d84> In [14]: ([2]).__hash__ # nothing. 

The fact is that set requires its elements to be hashable, i.e. implemented the __hash__ magic method (this is used for ordering in a tree, as far as I know). list does not implement this magic method, so it cannot be added to the set.

+4
source

Think of a constructor that looks something like this:

 class Set: def __init__(self,l): for elem in l: self.add(elem) 

Nothing too interesting to worry about why it takes lists, but on the other hand add(element) does not.

0
source

s.add ([10]) works as documented. An exception occurs because [10] is not hashed.

No magic happens during initialization.

set ([0,1,2,3,4,5,6,7,8,9]) has the same effect as set (range (10)), and sets (xrange (10)) and sets ( foo ()) where

 def foo(): for i in (9,8,7,6,5,4,3,2,1,0): yield i 

In other words, the arg argument must be iterable, and each of the values ​​obtained from the iterable must be hashed.

0
source

It behaves according to the documentation: set.add() adds one element (and since you give it a list, it complains that it does not shake - because lists are not good, like hash keys). If you want to add a list of elements, use set.update() . Example:

 >>> s = set([1,2,3]) >>> s.add(5) >>> s set([1, 2, 3, 5]) >>> s.update([8]) >>> s set([8, 1, 2, 3, 5]) 
0
source

Source: https://habr.com/ru/post/1340085/


All Articles