Warum ist es möglich, manchmal set () durch {} zu ersetzen?

73

Wenn ich in PyCharm schreibe:

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

Es heißt "Funktionsaufruf kann durch Set-Literal ersetzt werden" und ersetzt ihn durch:

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

Warum das? A set()in Python ist nicht dasselbe wie ein Wörterbuch {}?

Und wenn es dies optimieren will, warum ist das effektiver?

Olivier Pons
quelle
6
Beachten Sie, dass, trotz Ihrer Titel, Sie nicht können ersetzen set()mit {}, aber Sie können einen nicht leeren ersetzen set((1, 2, 3))mit einer wörtlichen {1, 2, 3}, denn jetzt ist es klar, dass kein Wörterbuch ist. Siehe docs.python.org/2/library/stdtypes.html#set-types-set-frozenset
jonrsharpe

Antworten:

105

Python-Sets und Wörterbücher können mit geschweiften Klammern erstellt werden:

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

my_set = {1, 2, 3}

Der Dolmetscher (und die menschlichen Leser) können sie anhand ihres Inhalts unterscheiden. Es ist jedoch nicht möglich, zwischen einem leeren Satz und einem leeren Diktat zu unterscheiden. Daher müssen Sie diesen Fall verwenden, set()damit leere Sätze eindeutig sind.

Ein sehr einfacher Test legt nahe, dass die wörtliche Konstruktion schneller ist (python3.5):

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

Diese Frage behandelt einige Probleme der Leistung von wörtlichen Konstruktionen über eingebaute Funktionen, wenn auch für Listen und Diktate. Die Zusammenfassung scheint zu sein, dass wörtliche Konstruktionen weniger Arbeit vom Interpreten erfordern.

snakecharmerb
quelle
Die wörtliche Konstruktion ist wahrscheinlich schneller, da Sie keine Zwischenliste erstellen. Was ist, wenn Sie das herausrechnen?
Jonrsharpe
4
@jonrsharpe scheint immer noch langsamer zu sein: timeit.timeit(stmt='a = set(mylist)', setup='mylist=[1, 2, 3]') -> 0.3987466390244663- Ich denke, der Link, den ich hinzugefügt habe, deckt einige davon ab.
Snakecharmerb
Wow in Python3.8, wenn Sie Ihre Tests ausprobieren, ist der Unterschied beeindruckend: 0.1970vs0.0705
Olivier Pons
9

Es ist eine alternative Syntax für 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

dictSyntax ist anders. Es besteht aus Schlüssel-Wert-Paaren. Zum Beispiel:

my_obj = {1:None, 2:None}
DhruvPathak
quelle
4

set([iterable])ist der Konstruktor zum Erstellen einer Menge aus der optionalen iterablen Datei iterable. Und {}soll Set / Dikt-Objektliterale erstellen. Was also erstellt wird, hängt davon ab, wie Sie es verwenden.

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
quelle
Wenn du sagst, set([iterable])meinst du die wörtlichen Zeichen [und ]tauchst auf? Oder verwenden Sie ABNF, um anzuzeigen, dass dies iterableein optionaler Parameter für die Funktion ist set()? Weil der erste Fall falsch ist, ist der zweite richtig. Es ist ziemlich verwirrend, weil viele Leute dies lesen und denken, Sie meinen den ersten Fall.
Buge
4

Ein weiteres Beispiel , wie setund {}ist nicht austauschbar (wie jonrsharpe erwähnt):

In: f = 'FH'

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

In: {f}
Out: {'FH'}
Emanuel
quelle
1
Funktionalität von set(f)mit Literalen muss Auspacken verwenden : {*f}.
IFcoltransG
Es ist nie zu ersetzen , set(somestuff)mit {somestuff}. Aber es ist möglich , zu ersetzen set([somestuff])mit , {somestuff}wenn somestuffnicht wörtlich 0 Zeichen in Ihrem Quellcode. Da OP 0 Zeichen verwendete set([somestuff])und somestuffnicht 0 war, war der Austausch möglich.
Buge