>>>
>>> s=set('cheeseshoi')
>>> s
set(['c', 'e', 'i', 'h', 'o', 's'])
>>>
>>>
>>> t=frozenset('bookshop')
>>>
>>> t
frozenset(['b', 'h', 'k', 'o', 'p', 's'])
跟数学概念中的集合一样,集合可以做join,-,包含,子集,超集等操作。
- len(s)
- Return the cardinality of set s.
- x in s
- Test x for membership in s.
- x not in s
- Test x for non-membership in s.
- issubset ( other ) ¶
- set <= other
- Test whether every element in the set is in other.
- set < other
- Test whether the set is a true subset of other, that is, set <= other and set != other.
- issuperset ( other ) ¶
- set >= other
- Test whether every element in other is in the set.
- set > other
- Test whether the set is a true superset of other, that is, set >=other and set != other.
- union ( other, ... ) ¶
- set | other | ...
-
Return a new set with elements from the set and all others.
Changed in version 2.6: Accepts multiple input iterables.
- intersection ( other, ... ) ¶
- set & other & ...
-
Return a new set with elements common to the set and all others.
Changed in version 2.6: Accepts multiple input iterables.
- difference ( other, ... ) ¶
- set - other - ...
-
Return a new set with elements in the set that are not in the others.
Changed in version 2.6: Accepts multiple input iterables.
- copy ( ) ¶
- Return a new set with a shallow copy of s.
-
-
>>>
>>> set('posh')==set('shop')
True
>>> -
-
>>> set('shop') <set('cheeseshop')
True
>>>
>>> set('bookshop')>=set('shop')
True
>>>
- 集合类型操作符:适合所有的集合类型
- union() 或者 |:集合并集
- & 集合交集intersection().
- -:取集合相对于前者的差集,difference()
- symmetric_difference() ^ 对称差
注意以上如果上述操作符的左边是可变set而右边是不可变set,则产生的结果为可变set,否则为不可变set
关于以上概念的数学涵义可以查离散数学。
以下操作符仅仅适用可变集合:
(Union) Update ( |= )
这个更新方法从已存在的集合中添加(可能多个)成员,此方法和update()等价.
>>> s = set('cheeseshop')
>>> u = frozenset(s)
>>> s |= set('pypi')
>>> s
set(['c', 'e', 'i', 'h', 'o', 'p', 's', 'y'])
保留/交集更新( &= )
保留(或交集更新)操作保留与其他集合的共有成员。此方法和intersection_update()等价.
>>> s = set(u)
>>> s &= set('shop')
>>> s
set(['h', 's', 'o', 'p'])
差更新 ( –= )
对集合s 和t 进行差更新操作s-=t,差更新操作会返回一个集合,该集合中的成员是集合s 去
除掉集合t 中元素后剩余的元素。此方法和difference_update()等价.
>>> s = set(u)
>>> s -= set('shop')
>>> s
set(['c', 'e'])
对称差分更新( ^= )
对集合s 和t 进行对称差分更新操作(s^=t),对称差分更新操作会返回一个集合,该集合中的成
员仅是原集合s 或仅是另一集合t 中的成员。此方法和symmetric_difference_update()等价.
>>> s = set(u)
>>> t = frozenset('bookshop')
>>> s ^= t
>>> s
set(['c', 'b', 'e', 'k'])
集合的内建方法:
- (所有的集合方法)
方法名称 操作
s.issubset(t) 如果s 是t 的子集,则返回True,否则返回False
s.issuperset(t) 如果t 是s 的超集,则返回True,否则返回False
s.union(t) 返回一个新集合,该集合是s 和t 的并集
s.intersection(t) 返回一个新集合,该集合是s 和t 的交集
s.difference(t) 返回一个新集合,该集合是s 的成员,但不是t 的成员
s.symmetric_difference(t) 返回一个新集合,该集合是s 或t 的成员,但不是s 和t 共有的成员
s.copy() 返回一个新集合,它是集合s 的浅复制
以下内容为转载:
set自python2.4中引入后,经过了多次的发展,在2.6中包括内建数据类型set、frozenset和基于字典的set、immutableset,后者作为前面版本的兼容,在2.6中已经不提倡使用。网络上现在已经有大量的关于set与fronzset的的文章,但是现有文章对于set和fronzenset分别在何时使用,两者的效率对比如何,介绍甚少。本文将从实际测试和源码分析两个角度就此进行分析。
一 只能用set
当集合对象会被改变时(例如添加、删除元素等),只能使用set
二 只能用frozenset
一般来说使用fronzet的地方都可以使用set,除了以下两种情况:
(1)作为可哈希对象使用
set和frozensdet最本质的区别是前者是可变的、后者是不可变的,这就导致了set是不可哈希的,而frozenset是可哈希的。因此当需要将集合作为字典的键值等需要可哈希对象的情况时,只能使用frozenset
(2)不希望集合被更改
python中包括list在内的大部分内型在进行参数传递时都采用的引用传递,这样函数对传入参数的改变将引用参数本身。当我们不希望函数改变集合时我们需使用frozenset
三 set与frozenset的运行效率比较
我们先生成一个10w的list,然后分别使用set和frozenset来构造集合,运行1w次。通过多次测试发现,数据波动较大。无法说明set和frozenset到底哪个效率高。
四 源码分析
既然通过直接测试无法得到高低之分,那么我们从源码来着手分析。 python的内建内型的实现都在object中,set和frozenset也不例外,两者都在Object/setobject.c中实现。
通过查看PySet_Type和PyFrozenSet_Type可以知道set使用set_new分配空间,set_init来初始化集合;frozenset使用frozenset_new分配空间,未提供初始化函数。set和frozeset的tp_alloc与tp_free函数相同,分别为PyType_GenericAlloc和PyObject_GC_Del。由于fronzeset没有提供初始化函数,所以数据的初始化是在分配空间时同步进行。
(一)set初始化
set_new函数直接调用make_new_set来生成为新的集合申请空间(传递给make_new_set的第二个参数为NULL)。空间的分配有两种方法:1 如果全局PySetObject数组(可存放80个)中存在空闲对象,则直接分配最后一个对象,然后将数据归零 2 否则使用PyType_GenericAlloc函数从内存池中分配空间。PyType_GenericAlloc函数为python通用的类型分配函数。
set_new函数执行完毕后,set_init函数将会得到调用。在set_init函数中首先调用set_clear_internal来释放空间中原有对象。然后调用set_update_internal来添加对象。由于在frozenset初始化也会调用该函数,所以该函数不会从效率上影响两种类型的初始化,此处我们不深入讨论该函数。 set_init函数执行完毕后,set初始化结束
(二)frozenset初始化
frozenset_new会对传入的迭代器做判断,如果传入的也是fronzenset对象的话则直接返回该迭代器本身。否则它同样是调用make_new_set来为新的集合申请空间,不同的是它会将传入的迭代器一并传递给make_new_set函数。在make_new_set完成如set中提到的一样的工作后,它判断迭代器是否为空,如果不为空它就调用set_update_internal来添加对象。
通过上面的分析可以看出在set初始化的过程中,会多调用一次set_clear_internal函数,所以从理论上来说frozenset会比set略快,但由于该函数的调用与传入的迭代器的大小无关,且在实际运行中其他因素的影响远大于该函数的调用,所以我们可以认为set和frozenset的速度是一样的。在两者都能用的情况下,建议使用frozenset,这样可以避免不小心对数据进行修改。
通过前面我们知道,set初始化时会多调用一次清楚表里面实际内容的函数,那么它为什么要执行这样的操作呢?以后的文章中我们将会对此进行解释。