Gibt es ein Python-Äquivalent zu Ruby-Symbolen?

75

Gibt es ein Python-Äquivalent zu Ruby-Symbolen?

  • Wenn ja, was ist es dann?

  • Wenn nicht, müssen wir dann nur noch Strings als Schlüssel in Wörterbüchern verwenden?

dreftymac
quelle
4
Im Anschluss an Ihrem Kommentar zu dieser Antwort unten : Wenn Sie etwas wollen , wo Sie eingeben können , d.banstatt d['b'], können Sie nur ein leeres verwenden class D(object): passeine Instanz zu erstellen , d = D()auf die Sie dann Ihre Werte Attribute zuweisen können Sie machen, wie so d.a=1und d.b=2und Natürlich bekommen ihre Werte so print(d.a + d.b). Ich bin mir nicht sicher, ob dies langsamer wäre als eine einfache Wörterbuchsuche wie d['b']in der Antwort.
FriendFX
Wenn Sie eine eindeutige Konstante wünschen, deren Datentyp keine Zeichenfolge ist, können Sie auch benutzerdefinierte Klassen dafür verwenden
Alexander Bird

Antworten:

76

Nein, Python hat keinen Symboltyp.

Zeichenfolgenliterale werden jedoch standardmäßig interniert, und andere Zeichenfolgen können mithilfe der internFunktion interniert werden . Die Verwendung von String-Literalen als Schlüssel in Wörterbüchern ist also nicht weniger leistungsfähig als die Verwendung von Symbolen in Ruby.

sepp2k
quelle
20
+1. Zum Glück für uns Ruby-Entwickler ist Performant kein Wort. (Sorry, wir sind nur so semantisch!): D
Wuputah
10
Der Hauptvorteil davon ist, dass die Sprache eine Kernsyntax und einen eingebauten Typ weniger hat. Es ist unnötig komplex in der Sprache, wenn es transparent gemacht werden kann.
Glenn Maynard
@Glenn Zuerst war ich verärgert zu hören, dass Python keine Symbole hatte und dass String-Literale als Schlüssel verwendet werden können. Das Problem ist, dass ich mit der Tatsache nicht zufrieden bin, dass ich alle meine Schlüssel in Anführungszeichen setzen muss. Gibt es einen Weg, dies zu umgehen?
1
@ J3M 7OR3: Nein, daran führt natürlich kein Weg vorbei. Aber bedenken Sie: Es ist nur ein zusätzliches Zeichen, und in echtem Code verwenden Sie ohnehin oft Variablen anstelle von Literalschlüsseln.
12
@delnan, natürlich gibt es einen Weg, dies zu umgehen: diktieren (a = 1, b = 2, c = 3).
Ned Batchelder
20

Wie andere gesagt haben, gibt es in Python kein Symbol, aber Zeichenfolgen funktionieren gut.

Verwenden Sie die Konstruktorsyntax dict (), um das Zitieren von Zeichenfolgen als Schlüssel zu vermeiden:

d = dict(
    a = 1,
    b = 2,
    c = "Hello there",
    )
Ned Batchelder
quelle
1
ironischerweise diese Lösung nicht , zumindest anfänglich, beschränken Sie Strings als Schlüssel zu haben.
Aaronasterling
Ja, es ist eine Umgehung, aber nur während des Zuweisungsschritts. Ich muss noch Anführungszeichen um das b in d ['b'] hinzufügen, um seinen Wert zu erhalten. Ich denke, ich erinnere mich nur daran, dass Rubinsymbole einfacher zu tippen waren. Ich wünschte, es gäbe ein Modul, das dieses Problem löst. Ich frage mich, ob das Programm dadurch langsamer laufen würde.
13

Auch für Interessierte: Symbole in Ruby, wenn sie in einem Hash verwendet werden, sind leeren Objekten in Python sehr ähnlich. Zum Beispiel könnten Sie tun:

some_var = object()

und setzen Sie dann einen Wörterbuchschlüssel als some_var:

some_dict = { some_var : 'some value' }

und dann einen Standardabruf durchführen:

some_dict[some_var]

Wie sepp2k jedoch feststellte, hat dies keinen Leistungsvorteil. Tatsächlich habe ich einen kurzen Test durchgeführt und wenig bis gar keine Leistungssteigerung festgestellt:

a, b, c, d, e = [object() for _ in range(5)]
dict_symbols = {a : 'a', b : 'b', c : 'c', d : 'd', e : 'e'}
dict_strings = {'a' : 'a', 'b' : 'b', 'c' : 'c', 'd' : 'd', 'e' : 'e'}

def run_symbols():
    for key in dict_symbols.keys():
        dict_symbols[key]

def run_strings():
    for key in dict_strings.keys():
        dict_strings[key]

Geschwindigkeit in Ipython getestet:

In [3]: %timeit run_symbols
10000000 loops, best of 3: 33.2 ns per loop

In [4]: %timeit run_strings
10000000 loops, best of 3: 28.3 ns per loop

In meinem Fall laufen die 'Symbole' also langsamer! (für lustige Zahlen, nicht genau). Es ist jedoch zu beachten, dass es auf diese Weise wahrscheinlich Speichervorteile gibt. Wenn Sie sich nicht für den Schlüsseltyp interessieren, haben Objekte eine geringere Stellfläche als Zeichenfolgen.

import sys
sys.getsizeof('some_var') # 45
some_var = object() 
sys.getsizeof(some_var) # 0

Dies wirft jedoch die Frage auf, wie Python den Speicher des Variablennamens some_var behandelt.

MartianE
quelle
Gute Antwort! Vielen Dank, dass Sie sich damit befasst haben.
Juno Woods
7
  1. Nein, es gibt kein Äquivalent.
  2. Nein, Sie können jedes hashbare Objekt als Wörterbuchschlüssel verwenden.
Philipp
quelle
Kann man einer Variablen ein String-Literal zuweisen und diese Variable dann als Schlüssel verwenden? zB orange = 'orange "food_type = {orange:' Frucht ', Banane:' Frucht '}
@ J3M 7OR3: Strings sind hashbar! Wie alle unveränderlichen Typen. In Bezug auf die zweite Frage ... Python ist kein Javascript - Schlüssel in Diktierliteralen sind nichts Besonderes. Sie können beliebige Ausdrücke sein (eine Variable, ein Literal, ...), ausgewertet und das Ergebnis als Schlüssel verwendet werden. Also ja, das funktioniert.
@delnan Ok. Aber ist die Verwendung einer Variablen anstelle eines String-Literals eine wichtige bewährte Methode? Tun die Leute das normalerweise? Oder können sie nur String-Literale (mit ihren Anführungszeichen) als Schlüssel verwenden?
1
@ J3M 7OR3: Wat? Meistens können Sie den Schlüssel zum Zeitpunkt des Schreibens des Programms unmöglich kennen. Natürlich k = "key"; d[k] = "value"ist das dumm (aber nicht for k in keys: d[k] = "default", obwohl es bessere Möglichkeiten gibt), aber wie bereits gesagt, verwenden Sie die meiste Zeit Laufzeitwerte als Schlüssel.