90

In PyCharm, when I write:

return set([(sy + ady, sx + adx)])

it says "Function call can be replaced with set literal" so it replaces it with:

return {(sy + ady, sx + adx)}

Why is that? A set() in Python is not the same as a dictionary {}?

And if it wants to optimize this, why is this more effective?

Olivier Pons
  • 15,363
  • 26
  • 117
  • 213
  • 9
    Note that, despite your title, you **cannot** replace `set()` with `{}`, but you *can* replace a non-empty `set((1, 2, 3))` with a literal `{1, 2, 3}`, because now it's clear that's not a dictionary. See https://docs.python.org/2/library/stdtypes.html#set-types-set-frozenset – jonrsharpe Apr 17 '16 at 08:09

4 Answers4

130

Python sets and dictionaries can both be constructed using curly braces:

my_dict = {'a': 1, 'b': 2}

my_set = {1, 2, 3}

The interpreter (and human readers) can distinguish between them based on their contents. However it isn't possible to distinguish between an empty set and an empty dict, so this case you need to use set() for empty sets to disambiguate.

A very simple test suggests that the literal construction is faster (python3.5):

>>> timeit.timeit('a = set([1, 2, 3])')
0.5449375328607857
>>> timeit.timeit('a = {1, 2, 3}')
0.20525191631168127

This question covers some issues of performance of literal constructions over builtin functions, albeit for lists and dicts. The summary seems to be that literal constructions require less work from the interpreter.

Community
  • 1
  • 1
snakecharmerb
  • 47,570
  • 11
  • 100
  • 153
  • The literal construction is probably faster because you don't build an intermediate list; what if you factor that out? – jonrsharpe Apr 17 '16 at 08:12
  • 4
    @jonrsharpe still seems slower: `timeit.timeit(stmt='a = set(mylist)', setup='mylist=[1, 2, 3]') -> 0.3987466390244663` - I think the link I added covers some of this. – snakecharmerb Apr 17 '16 at 08:14
  • Wow in Python3.8, trying your tests, the difference is impressive: `0.1970` vs `0.0705` – Olivier Pons Feb 27 '20 at 04:45
9

It is an alternative syntax for set()

>>> a = {1, 2}
>>> b = set()
>>> b.add(1)
>>> b.add(2)
>>> b
set([1, 2])
>>> a
set([1, 2])
>>> a == b
True
>>> type(a) == type(b)
True

dict syntax is different. It consists of key-value pairs. For example:

my_obj = {1:None, 2:None}
Ulf Gjerdingen
  • 1,414
  • 3
  • 16
  • 20
DhruvPathak
  • 42,059
  • 16
  • 116
  • 175
7

Another example how set and {} are not interchangeable (as jonrsharpe mentioned):

In: f = 'FH'

In: set(f)
Out: {'F', 'H'}

In: {f}
Out: {'FH'}
Emanuel
  • 422
  • 7
  • 12
  • 2
    Functionality of `set(f)` with literals must use unpacking: `{*f}`. – IFcoltransG Nov 22 '19 at 07:29
  • It's never possible to replace `set(somestuff)` with `{somestuff}`. But it is possible to replace `set([somestuff])` with `{somestuff}` whenever `somestuff` is not literally 0 characters in your source code. Since OP was using `set([somestuff])` and `somestuff` wasn't 0 characters, that's why the replacement was possible. – Buge Dec 15 '19 at 01:04
4

set([iterable]) is the constructor to create a set from the optional iterable iterable. And {} is to create set / dict object literals. So what is created depends on how you use it.

In [414]: x = {}

In [415]: type(x)
Out[415]: dict

In [416]: x = {1}

In [417]: type(x)
Out[417]: set

In [418]: x = {1: "hello"}

In [419]: type(x)
Out[419]: dict
C Panda
  • 3,297
  • 2
  • 11
  • 11
  • 1
    When you say `set([iterable])` do you mean the literal characters `[` and `]` show up? Or are you using ABNF to indicate that `iterable` is an optional parameter to the function `set()`? Because the first case is wrong, the second case it correct. It's quite confusing because many people will read this and think you mean the first case. – Buge Dec 15 '19 at 01:44