空集合字面量?

607

[] = 空 list

() = 空 tuple

{} = 空 dict

那么空的 set 有类似的符号表示吗?还是必须写成 set()


26
你不接受 {i for i in []},是吗? - utdemir
7
是的,你可以用许多繁琐的方式完成几乎所有操作。我在我的代码示例中不会添加 map(lambda x: x) 只是为了展示它的工作原理。这也不是一个集合字面值,而只是一个集合推导式。 - user395760
193
一个简单的方法是 {0}-{0},虽然不如 set() 显式,但它有一个好处,看起来像一双有趣的眼睛。 - wim
13
@Chris {}是一个字典。{0}是一个集合。{0} - {0}表示一个集合减去它自己,也就是空集合。 - michaelsnowden
4
@Kade 的说法正确。在Python中,函数调用速度相当慢(主要归因于堆栈操作开销),因此无需调用的解决方案总是更快的 -- 例如 f{a}' 要比 str(a) 快。{*''} 的问题仅仅是速度上的收益并没有真正值得暂时混淆读你代码的所有人(如果你没有使用pypy,微小的优化在Python中几乎从来不重要)。 - user4698348
显示剩余8条评论
7个回答

681

没有专门表示空集合的文字语法。你需要写成 set()


你的意思是说没有用于表示空集合的文字语法?还是说一般来讲集合都没有文字语法? - Johan Råde
18
有一些固定的文字,但只在Python 3.x中。无论如何,都没有空集合的文字。 - user395760
4
这个语言手册在这个问题上非常清晰。http://docs.python.org/library/stdtypes.html#set-types-set-frozenset 上说, "非空集合......可以通过在大括号内放置一个逗号分隔的元素列表来创建" - S.Lott
47
实际上,集合字面量已经被移植到Python 2.7中,因此它们不仅仅在Python 3中可用。 - Jim Brissom
15
@andy 这不是一个空集合 - 它包含数字1。顺便说一下,你不需要加逗号 - 这只对元组有要求。 - sepp2k

98

毫无疑问,请使用set()来创建一个空集合。

但是,如果你想给人留下印象,告诉他们你可以使用Python >= 3.5的字面量和*来创建一个空集合(参见PEP 448),可以这样做:

>>> s = {*()}  # or {*{}} or {*[]}
>>> print(s)
set()

这基本上是一种更简洁的做法{_ for _ in ()},但是,请不要这样做。


1
为什么?!性能几乎相同: $ python3.7 -m timeit 'set()' 2000000 次循环, 最好的 5 次: 177 纳秒每个循环 $ python3.7 -m timeit '{*()}' 2000000 次循环, 最好的 5 次: 171 纳秒每个循环 - ogurets
42
@ogurets,“set()” 对于代码维护者来说更容易理解,这通常比性能更重要。"{*()}" 在某种程度上显得“狡猾”,几乎带有贬义意味。 - benjimin
2
呵呵,那很聪明。 - Ekrem Dinçel
3
如果你想要“给人留下印象”,你会说什么? - Dustin Oprea
假设您在文件中有许多非空集合,突然需要编写一个空集合(例如尚未实现),为了保持一致性,最好以这种方式声明一个集合。 - LMCuber

52

仅为扩展已接受的答案:

从版本2.73.1开始,Python就支持了set字面量{}的形式,例如使用{1,2,3},但{}本身仍然用于表示空字典。

Python 2.7(第一行在Python <2.7中无效)

>>> {1,2,3}.__class__
<type 'set'>
>>> {}.__class__
<type 'dict'>

Python 3.x

>>> {1,2,3}.__class__
<class 'set'>
>>> {}.__class__
<class 'dict'>

更多信息请查看:https://docs.python.org/3/whatsnew/2.7.html#other-language-changes


14
答案错误。仍然没有字面语法来表示一个空集合。{}.__class__仍将返回dict - Ninja420
12
@Ninja420请先阅读再评论,我已经注意到了。 - Reishin
5
被接受的答案仍然是正确的,没有过时。空集合 没有字面语法,但是空字典有一个。 - AndreasHassing
2
对于空的情况,@AndreasBjørn是可以的,但是对于非空的情况,你会得到PEP8异常并建议使用集合字面量。 - Reishin
4
实际上,在Python 3.6中,{}.__class__返回的是<class 'dict'>而不是<type 'dict'> - Tsonglew

11
是的。对于非空的字典/集合,相同的表示法也适用于空的字典/集合。
请注意非空字典和集合字面值之间的区别:
{1: 'a', 2: 'b', 3: 'c'} -- 字典中有一些键值对
{'aaa', 'bbb', 'ccc'} -- 集合中有一些值

所以:
{} == 零个键值对 == 空字典
{*()} == 空元组的值 == 空集合

然而,你能这样做并不意味着你应该这样做。除非你有一些强烈的理由,最好明确地构造一个空集合,例如:
a = set()

Performance:

The literal is ~15% faster than the set-constructor (CPython-3.8, 2019 PC, Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz):

>>> %timeit ({*()} & {*()}) | {*()}
214 ns ± 1.26 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

>>> %timeit (set() & set()) | set()
252 ns ± 0.566 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

... and for completeness, Renato Garcia's frozenset proposal on the above expression is some 60% faster!

>>> ϕ = frozenset()

>>> %timeit (ϕ & ϕ) | ϕ
100 ns ± 0.51 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
注意:正如ctrueden在评论中指出的那样,{()}不是一个空集合。它是一个只有一个元素的集合:空元组。

3
{()} 不是空集合。它是一个只有一个元素的单例集合,该元素为一个空元组。你可以通过检查 len({()})(结果应为1)或 () in {()} (结果应为 True)来验证这一点。 - ctrueden
2
哎呀,你说得对!我更新了帖子:添加了关于{()}不是空集的注释,以防其他人犯同样的错误。谢谢你,@ctrueden! - pycoder

6

这取决于您是想用于比较还是用于赋值。

如果您想使现有的集合为空,可以使用.clear()方法,特别是如果您想避免创建新对象。如果您想进行比较,请使用set()或检查长度是否为0。

例如:

#create a new set    
a=set([1,2,3,'foo','bar'])
#or, using a literal:
a={1,2,3,'foo','bar'}

#create an empty set
a=set()
#or, use the clear method
a.clear()

#comparison to a new blank set
if a==set():
    #do something

#length-checking comparison
if len(a)==0:
    #do something

10
a=set()并不会清空set,而是创建一个新的set并将其赋值给a,覆盖先前的任何值。 - gerrit
确实。这就是我说如果你想避免创建一个新对象,你应该使用clear()的原因。我想我的评论应该稍微改一下措辞。 - Brian Minton
似乎使用 a.clear() 方法比 a=set() 稍微快一些,而检查 len(a)==0 比检查等于 a==set() 稍微快一些。 - Brian Minton
4
与其写if len(a)==0:,写成if a:即可(更符合Python语言风格)。需要注意的是,如果你需要匹配条件的极性,则应该写成if not a: - Jim Oldfield

3

除了疯狂的想法之外:由于Python 3接受unicode标识符,因此您可以声明一个变量ϕ = frozenset()(ϕ是U+03D5),并使用它代替其他变量。


4
问题在于,set对象是可变的,所以使用 spam = ϕ; spam.add("eggs") 会让你处于风险之中。 - drdaeman
4
如果ϕ是一个冻结集合,那么尝试执行spam.add("eggs")操作将会失败,因为冻结集合对象没有任何add方法。 - Brian Minton
1
@BrianMinton:但这是预期的行为。请注意,当有人写span = ϕ时,spanϕ将指向同一对象,即id(span)== id(ϕ)。因此,如果spam.add(“eggs”)可以工作,那么ϕ对象将不再是一个空集,我们将回到drdaeman指出的原始问题 - Renato Garcia
1
与空字典文字进行比较:`>>> a={}
a['foo']='bar' a {'foo': 'bar'} `
- Brian Minton
5
дёәд»Җд№ҲдёҚдҪҝз”ЁвҖңз©әйӣҶвҖқз¬ҰеҸ·пјҲU+2205пјүвҲ…е‘ўпјҹиҜ·зҝ»иҜ‘жӯӨеҸҘгҖӮ - ankostis

-5

在Python中有几种创建空集合的方法:

  1. 使用set()方法
    这是Python中的内置方法,用于在变量中创建空集合。
  2. 使用clear()方法(创造性工程师技巧哈哈)
    看这个例子:

    sets={"Hi","How","are","You","All"}
    type(sets) (这一行输出:set)
    sets.clear()
    print(sets)  (这一行输出:{})
    type(sets) (这一行输出:set)

所以,这是两种创建空集合的方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接