头图

Python has a built-in immutable collection object: frozenset. As the name suggests, this collection object cannot be modified once it is created.

concept

The following code demonstrates the difference in the usage of mutable and immutable collections:

l = [1, 2, 3, 4]
new_set = set(l)
new_set.remove(1)
print (new_set)

fset = frozenset(l)
fset.remove(1)

If you run this code, its output will be:

{2, 3, 4}

Traceback (most recent call last):
  File "main.py", line 9, in <module>
    fset.remove(1)
AttributeError: 'frozenset' object has no attribute 'remove'

You can see that the frozenset instance does not have a remove method at all, and of course it does not have an append method, and you cannot use index to assign values to elements.

effect

All uses of frozenset are the same as normal sets, except that they are not modifiable.

What is the use of such an immutable collection? There should be no help for performance. An article once pointed out that it is slightly slower than ordinary set. The main value is still reflected in readability and safety:

  • Explicitly declares that the collection is immutable, and gives users a clear prompt. Once misused, the runtime will also report a friendly error;
  • If you want to put this set into another set, or as the key of a dict, it must be immutable

This second point is mainly because the key of the dict is unique (or the elements in the set are also unique). If an object is passed, python will try to call its hash method to generate a hash string as a judgment of whether it is unique or not. According to, and if the object is actually mutable, its content will affect the value of the hash string. So in python, mutable objects have no built-in hash method at all to avoid it being used as a key.

For example the following code:

fset = frozenset({4, 5})
s = {1, 2, fset}
print (s)

s = {1, 2, {4, 5}}

First define a frozenset and insert it into a normal set; the last sentence tries to initialize another normal set in the normal set. The output is as follows:

{frozenset({4, 5}), 1, 2}

Traceback (most recent call last):
  File "main.py", line 27, in <module>
    s = {1, 2, {4, 5}}
TypeError: unhashable type: 'set'

It can be seen that ordinary set cannot be used as an element of another set, but frozenset can. '

Why does Java not have this limitation

Java programmers may find it strange, isn't it normal to put a mutable object in a hashset? Why not? We often write in Java like this:

HashSet<ArrayList<String>> masterCollection = new HashSet<ArrayList<String>>();
ArrayList<String> a = new ArrayList<String>();
masterCollection.add(a);
a.add("Hello, World");
for(ArrayList<String> list : masterCollection) {
    // do something to list
}

No error at all.

So, is the implementation mechanism of Java different from that of Python?

The answer is no, Java just "tolerates" possible errors - This thread explains it very well. simply put:

Both Java and Python use the hash value of an object as the key. Compared with Python, data consistency is more important, and Java is more flexible, so if we really put a mutable object in the HashSet and change it afterwards Its value, then you will find that the HashSet collection can no longer detect its existence!

mutable set as key in java.png


songofhawk
303 声望24 粉丝