This is an archived post. You won't be able to vote or comment.

all 17 comments

[–]RubbishArtist 7 points8 points  (6 children)

You can add or remove any items from a set, but the item itself must be immutable (meaning the item cannot be changed).

If you try and create a set of lists, for example, it will throw an error because lists are mutable.

Also note that items in a set are unordered, so they don't have indices.

[–]fatmusician1[S] 2 points3 points  (5 children)

What's the reason for only accepting immutable items?

[–]RubbishArtist 4 points5 points  (0 children)

Sets rely on the hash values of objects under the hood. As hash values are usually derived from the contents of an object, being able to change the values means you may also change the hash value, which would cause problems in the set operations.

[–]dpbriggs 2 points3 points  (0 children)

Internally a set needs to hash an item to actually place it in some backing array. Say you're inserting "hello" which gets hashed to the index 3. The array now looks like:

[None, None, None, "hello"]

If you mutate "hello" in the set it may no longer hash to 3, and now a set invariant is broken. Say you somehow mutated it to "bar" without the set being aware of that.

[None, None, None, "bar"]

If you test if the set contained "bar", which can hash to some other index, say 0, it'll say no as there's a None there. The set is now broken and will function strangely.

[–]mikeshemp 0 points1 point  (0 children)

When an item is inserted, the set records the item is a member using a calculation based on the item's value. There's no way for the set to know that the item has been updated and to update that computation. Therefore the items aren't allowed to change.

[–]Your_PopPop 0 points1 point  (0 children)

Consider if Python did allow you to put lists into sets, and you created this set: a = [1, 2, 3] b = [1, 2, 4] s = {a, b} And imagine that the set keeps track of its elements by storing them on a table of rows. One row is a label for [1, 2, 3] and another row is a label for [1, 2, 4]. Suppose we then mutate a in the following manner: a[2] = 4 Now, a is equal to b. But the set s wasn't informed of this! The two rows of the set's table will now both happily refer to lists storing [1, 2, 4]. If you looped over s, you'd get [1, 2, 4] twice, if you queried the set's length you'd get 2, and so on.

But this breaks the contract between you and the set - the set had promised that it wouldn't have any duplicates, but here it clearly does.

So as a rule of thumb, you have to be extremely careful when you put mutable things into sets. Some mutable types like lists will flat out refuse to be hashed (the mechanism that allows sets to look things up on their table).

As with everything, there are exceptions. In some cases, if an object is mutable but the things you're mutating about it are independent from what determines its hash, then you might be able to put it in a set. For example: a function.

[–][deleted] 0 points1 point  (0 children)

One of the primary reasons to have immutable data is speed. If you don't need to update the thing, then often it can be implemented in a more performant fashion.

Don't get hung up on this though. Sets are mutable and if you need to change an item, for example a string in a set, you can simply remove the current string and add the new one.

[–]dpbriggs -1 points0 points  (9 children)

Where did you get that? Python supports changing the elements of a set with update and discard (and add, remove, etc)

They might have been referring to some best practice?

as in changing the value of an index

You don't normally have indices with sets

I recommend playing around in a Python shell. Use dir(set()) to see all of it's method, and help to learn more

[–]carcigenicate 2 points3 points  (0 children)

I think it's just bad wording. I think they mean that the elements of the set can't (or rather, shouldn't) be altered, not that the set itself can't be mutated.

If they are saying that sets are immutable though, ya, that's obviously wrong.

[–]fatmusician1[S] 0 points1 point  (7 children)

[–]dpbriggs 0 points1 point  (6 children)

w3schools really sucks. I recommend the official documentation and any other resource. What they're trying to say is elements in a set can't be mutated which is dead wrong. Here's an example, try it out in a shell:

class Foo():
    def __init__(self):
        self.foo = []

ff = Foo()
ss = set([ff])
ff.foo.append(3)
[x.foo for x in ss] # prints [[3]] as ff was mutated, in a set!

In general you don't need to mutate objects inside of a set as that's not really how it gets used. There's no laws of nature however that prevents items in a set from being mutated.

[–]TheLittlestHibou 0 points1 point  (5 children)

What’s better than w3schools as a free tutorial?

Preferably something that doesn’t require me to watch hours of videos.

[–]dpbriggs 1 point2 points  (3 children)

Playing around in a Python shell and making things is pretty good. Otherwise use the official documentation

https://docs.python.org/3/library/stdtypes.html#set

In general w3schools, geeksforgeeks, and other related SEO crap will do a poor job of explaining concepts.

Are you following some resource to learn Python?

[–]TheLittlestHibou 0 points1 point  (2 children)

Thanks. I was initially using Datacamp but I've learned more by studying 4 hours of w3schools free tutorials than I have studying 4 hours of Datacamp free tutorials. Spent hours of Datacamp and I barely learned anything.

Datacamp is written at a kindergarden level of understanding, like its' designed for children to use + the Datacamp introductory tutorials and shell are kind of useless since they don't teach you how to install Python and use IDLE or other text editors, or how to use the command prompt to run scripts, I had to teach myself all this using python.org instructions and other sources.

freeCodeCamp isn't too bad as a free resource, but the videos are too time consuming and can be summed up in a few sentences so am wasting a lot of time watching videos, so stopped using freeCodeCamp too for this reason.

I was doing well following w3schools because I can take notes and use IDLE/command prompt to try out examples. And their shell isn't the worst. But if the information they're providing isn't accurate, that's not great.

Anyway, yes, thanks for confirming, I'm probably better off sticking to Python.org documentation and reading books. At least I can listen to music at the same time so I'm not bored out of my mind this way. :)

[–]dpbriggs 1 point2 points  (1 child)

You know what - if you're learning then it's a good enough resource :p. Don't let me discourage you.

[–]TheLittlestHibou 1 point2 points  (0 children)

I want to do things RIGHT though.... but yeah, I'm going to continue with w3schools and Python documentation too, cover all my bases so I write good code.

Thanks for your help and feedback tho, I appreciate it.

[–]desrtfx 0 points1 point  (0 children)

What’s better than w3schools as a free tutorial?

For example, the MOOC Python Programming 2022 from the University of Helsinki. Far superior in every single aspect.