Use curly braces to initialize a Set in Python

Question:

I’m learning python, and I have a novice question about initializing sets. Through testing, I’ve discovered that a set can be initialized like so:

my_set = {'foo', 'bar', 'baz'}

Are there any disadvantages of doing it this way, as opposed to the standard way of:

my_set = set(['foo', 'bar', 'baz'])

or is it just a question of style?

Asked By: fvrghl

||

Answers:

There are two obvious issues with the set literal syntax:

my_set = {'foo', 'bar', 'baz'}
  1. It’s not available before Python 2.7

  2. There’s no way to express an empty set using that syntax (using {} creates an empty dict)

Those may or may not be important to you.

The section of the docs outlining this syntax is here.

Answered By: bgporter

From Python 3 documentation (the same holds for python 2.7):

Curly braces or the set() function can be used to create sets. Note:
to create an empty set you have to use set(), not {}; the latter
creates an empty dictionary, a data structure that we discuss in the
next section.

in python 2.7:

>>> my_set = {'foo', 'bar', 'baz', 'baz', 'foo'}
>>> my_set
set(['bar', 'foo', 'baz'])

Be aware that {} is also used for map/dict:

>>> m = {'a':2,3:'d'}
>>> m[3]
'd'
>>> m={}
>>> type(m)
<type 'dict'> 

One can also use comprehensive syntax to initialize sets:

>>> a = {x for x in """didn't know about {} and sets """ if x not in 'set' }
>>> a
set(['a', ' ', 'b', 'd', "'", 'i', 'k', 'o', 'n', 'u', 'w', '{', '}'])
Answered By: 0x90

Compare also the difference between {} and set() with a single word argument.

>>> a = set('aardvark')
>>> a
{'d', 'v', 'a', 'r', 'k'} 
>>> b = {'aardvark'}
>>> b
{'aardvark'}

but both a and b are sets of course.

Answered By: Thruston

You need to do empty_set = set() to initialize an empty set. {} is an empty dict.

Answered By: Arjjun

I’m surprised nobody has mentioned this, but it appears there is actually a difference between those two syntaxes from what I can tell—and that is performance/optimization.

For most situations the difference should be negligible, but in your example the following is creating a set from items directly:

my_set = {'foo', 'bar', 'baz'}

While the following creates a list and then passes it to the set constructor:

my_set = set(['foo', 'bar', 'baz'])

The end results are equivalent, but we’re getting them two slightly different ways. As you’d expect, the second one is a bit slower:

❯ python -m timeit 'my_set = {"foo", "bar", "baz"}'
10000000 loops, best of 5: 37.3 nsec per loop

❯ python -m timeit 'my_set = set(["foo", "bar", "baz"])'
5000000 loops, best of 5: 92.3 nsec per loop

As far as I’m aware, the {} literal syntax is the only way to skip creating an intermediate iterable when constructing a set. It’s a little odd to me personally that the set constructor wasn’t instead designed to take a variable number of positional arguments like so:

# This usage is invalid in real Python. If it existed,
# I would expect the call to be exactly equivalent
# to the performance of the literal syntax.
>>> set("foo", "bar", "baz")

# You would then construct a `set` from an existing
# `list` by simply unpacking the sequence.
>>> set(*["foo", "bar", "baz"])

Unfortunately, that signature doesn’t exist.

Answered By: Aaron Beaudoin
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.