Python中的不可变集合
Python内置了一个不可变(immutable)集合对象:frozenset,顾名思义,这种集合对象,一旦创建了就不能修改。
概念
下面的代码演示了可变和不可变集合使用上的差别:
l = [1, 2, 3, 4]
new_set = set(l)
new_set.remove(1)
print (new_set)fset = frozenset(l)
fset.remove(1)
如果运行这段代码,它的输出会是:
{2, 3, 4}Traceback (most recent call last):
File "main.py", line 9, in
fset.remove(1)
AttributeError: 'frozenset' object has no attribute 'remove'
可以看到frozenset实例根本没有remove方法,当然它也没有append方法,不能用index给元素赋值。
作用
除了不可修改以外,frozenset所有的用法都和普通set一样。
这样一个不可变的集合,有什么用呢?对性能应该没有什么帮助,曾经有文章指出它比普通的set还稍慢一点,主要价值还是体现在可读性和安全性上:
- 显式地声明了该集合是不可更改的,给使用者明确提示,一旦误用了,运行时也会友好报错;
- 如果想把这个集合,放到另一个set里面,或者作为dict的key,那它就必须是不可更改的
比如下面这段代码:
fset = frozenset({4, 5})
s = {1, 2, fset}
print (s)s = {1, 2, {4, 5}}
首先定义了一个frozenset,把它插入一个普通set;最后一句试图在普通set里面,初始化另外一个普通set。输出结果如下:
{frozenset({4, 5}), 1, 2}Traceback (most recent call last):
File "main.py", line 27, in
s = {1, 2, {4, 5}}
TypeError: unhashable type: 'set'
可见普通set是不能作为另外一个set的元素的,但frozenset就可以。‘
为什么Java没有这个限制
Java程序员可能会觉得奇怪,在hashset里放一个可变对象,不是很正常么?凭什么不行啊,我们Java经常这样写:
HashSet> masterCollection = new HashSet>();
ArrayList a = new ArrayList();
masterCollection.add(a);
a.add("Hello, World");
for(ArrayList list : masterCollection) {
// do something to list
}
完全不会报错么。
So,难道Java的实现机制和Python不一样?
【Python中的不可变集合】答案是并没有,Java只是“容忍”了可能发生的错误——这个帖子解释得很清楚。简单来说:
Java和Python都是用一个对象的hash值作为key的,相比Python更重视数据一致性,Java更看中灵活性,所以如果我们真的在HashSet里放了一个可变对象,并且事后改变了它的值,那么就会发现,HashSet集合,已经检测不到它的存在了!
文章图片
推荐阅读
- 热闹中的孤独
- JS中的各种宽高度定义及其应用
- 我眼中的佛系经纪人
- 《魔法科高中的劣等生》第26卷(Invasion篇)发售
- python学习之|python学习之 实现QQ自动发送消息
- Android中的AES加密-下
- 逻辑回归的理解与python示例
- 放下心中的偶像包袱吧
- C语言字符函数中的isalnum()和iscntrl()你都知道吗
- C语言浮点函数中的modf和fmod详解