Are Python sets mutable?

Question:

Are sets in Python mutable?


In other words, if I do this:

x = set([1, 2, 3])
y = x

y |= set([4, 5, 6])

Are x and y still pointing to the same object, or was a new set created and assigned to y?

Asked By: Hubro

||

Answers:

print x,y

and you see they both point to the same set:

set([1, 2, 3, 4, 5, 6]) set([1, 2, 3, 4, 5, 6])
Answered By: eumiro
>>>> x = set([1, 2, 3])
>>>> y = x
>>>> 
>>>> y |= set([4, 5, 6])

>>>> print x
set([1, 2, 3, 4, 5, 6])
>>>> print y
set([1, 2, 3, 4, 5, 6])
  • Sets are unordered.
  • Set elements are unique. Duplicate elements are not allowed.
  • A set itself may be modified, but the elements contained in the set must be of an immutable type.
set1 = {1,2,3}

set2 = {1,2,[1,2]}  --> unhashable type: 'list'
# Set elements should be immutable.

Conclusion: sets are mutable.

Answered By: Tom van der Woerdt

Your two questions are different.

Are Python sets mutable?

Yes: “mutable” means that you can change the object. For example, integers are not mutable: you cannot change the number 1 to mean anything else. You can, however, add elements to a set, which mutates it.

Does y = x; y |= {1,2,3} change x?

Yes. The code y = x means “bind the name y to mean the same object that the name x currently represents”. The code y |= {1,2,3} calls the magic method y.__ior__({1,2,3}) under the hood, which mutates the object represented by the name y. Since this is the same object as is represented by x, you should expect the set to change.


You can check whether two names point to precisely the same object using the is operator: x is y just if the objects represented by the names x and y are the same object.

If you want to copy an object, the usual syntax is y = x.copy() or y = set(x). This is only a shallow copy, however: although it copies the set object, the members of said object are not copied. If you want a deepcopy, use copy.deepcopy(x).

Answered By: Katriel

I don’t think Python sets are mutable as mentioned clearly in book "Learning Python 5th Edition by Mark Lutz – O’Reilly Publications"

Enter image description here

Answered By: person

After changing the set, even their object references match. I don’t know why that textbook says sets are immutable.

    >>> s1 ={1,2,3}
    >>> id(s1)
    140061513171016
    >>> s1|={5,6,7}
    >>> s1
    {1, 2, 3, 5, 6, 7}
    >>> id(s1)
    140061513171016
Answered By: Ashfaq Ur Rahman N

Python sets are classified into two types. Mutable and immutable. A set created with ‘set’ is mutable while the one created with ‘frozenset’ is immutable.

>>> s = set(list('hello'))
>>> type(s)
<class 'set'>

The following methods are for mutable sets.

s.add(item) — Adds item to s. Has no effect if listis already in s.

s.clear() — Removes all items from s.

s.difference_update(t) — Removes all the items from s that are also in t.

s.discard(item) — Removes item from s. If item is not a member of s, nothing happens.

All these operations modify the set s in place. The parameter t can be any object that supports iteration.

Answered By: vivek

Sets are muttable

s = {2,3,4,5,6}
type(s)
<class 'set'>
s.add(9)
s
{2, 3, 4, 5, 6, 9}

We are able to change elements of set

Answered By: Shashank Sahay

Yes, Python sets are mutable because we can add, delete elements into set, but sets can’t contain mutable items into itself. Like the below code will give an error:

s = set([[1,2,3],[4,5,6]])

So sets are mutable but can’t contain mutable items, because set internally uses hashtable to store its elements so for that set elements need to be hashable.
But mutable elements like list are not hashable.

Note:
Mutable elements are not hashable
Immutable elements are hashable

Just like key of a dictionary can’t be a list.

Answered By: Prabhjyot Singh

Sets are mutable, you can add to them. The items they contain CAN BE MUTABLE THEY MUST BE HASHABLE. I didn’t see any correct answers in this post so here is the code

class MyClass:
"""
    This class is hashable, however, the hashes are
    unique per instance not the data so a set will
    have no way to determine equality
"""
def __init__(self):
    self.my_attr = "no-unique-hash"
def __repr__(self):
    return self.my_attr

class MyHashableClass:
    """
        This object implements __hash__ and __eq__ and will
    produce the same hash if the data is the same. 
    That way a set can remove equal objects.
    """
    def __init__(self):
        self.my_attr = "unique-hash"
    def __hash__(self):
        return hash(str(self))
    def __eq__(self, other):
        return hash(self) == hash(other)
    def __repr__(self):
        return self.my_attr

myclass_instance1 = MyClass()
myclass_instance2 = MyClass()

my_hashable_instance1 = MyHashableClass()
my_hashable_instance2 = MyHashableClass()

my_set = {
    myclass_instance1,
    myclass_instance2,
    my_hashable_instance1,
    my_hashable_instance2, # will be removed, not unique
} # sets can contain mutuable types
# The only objects set can not contain are objects
# with the __hash__=None, such as List, Dict, and Sets

print(my_set)
# prints {unique-hash, no-unique-hash, no-unique-hash }

my_hashable_instance1.my_attr = "new-hash"  # mutating the object

# now that the hashes between the objects are differrent
# instance2 can be added
my_set.add(my_hashable_instance2) 

print(my_set)
# {new-hash, no-unique-hash, no-unique-hash, unique-hash}
Answered By: daniel blanco
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.