2015-01-08 8 views
8

Ich habe festgestellt, dass viele Bibliotheken heutzutage die Verwendung von Strings über Enum-Typ-Variablen für Parameter bevorzugen.Enum vs String als Parameter in einer Funktion

Wo Leute vorher enums verwenden würden, z.B. dateutil.rrule.FR für einen Freitag, es scheint, dass dies in Richtung zur Verwendung von Zeichenfolge verschoben wurde (z. B. 'FRI').

Same in numpy (oder pandas was das betrifft), wobei searchsorted beispielsweise verwendet von Zeichenketten (z.B. Seite = 'links' oder Seite = 'rechts') und nicht als eine definierte ENUM. Zur Vermeidung von Missverständnissen vor Python 3.4 dies leicht als Enum als solche umgesetzt worden sein könnte:

class SIDE: 
    RIGHT = 0 
    LEFT = 1 

Und die Vorteile von Aufzählungen Variable vom Typ sind klar: Sie sie nicht falsch schreiben kann einen Fehler ohne Anheben, Sie bieten eine angemessene Unterstützung für IDEs usw.

Warum also überhaupt Strings verwenden, statt Enumerationstypen beizubehalten? Macht dies die Programme nicht viel anfälliger für Benutzerfehler? Es ist nicht so, dass Enums einen Overhead erzeugen - wenn überhaupt sollten sie etwas effizienter sein. Wann und warum hat dieser Paradigmenwechsel stattgefunden?

Antwort

2

IMHO ist es eine Frage des Geschmacks. Einige Leute mögen diesen Stil:

def searchsorted(a, v, side='left', sorter=None): 
    ... 
    assert side in ('left', 'right'), "Invalid side '{}'".format(side) 
    ... 

numpy.searchsorted(a, v, side='right') 

Ja, wenn Sie searchsorted mit side='foo' nennen Sie eine AssertionError Weise später zur Laufzeit - aber zumindest wird der Fehler recht einfach zu erkennen, die Zurückverfolgungs suchen.

Während andere Menschen es vorziehen, können (für die Vorteile hervorgehoben Sie):

numpy.searchsorted(a, v, side=numpy.CONSTANTS.SIDE.RIGHT) 

favorisieren ich die erste, weil ich selten benutzte Konstanten denken, sind die Namespace cruft nicht wert. Sie können anderer Meinung sein, und die Leute können sich aufgrund anderer Bedenken auf beide Seiten ausrichten.

Wenn Sie wirklich, nichts verhindert, dass Sie Ihre eigenen „Aufzählungen“ definieren:

class SIDE(object): 
    RIGHT = 'right' 
    LEFT = 'left' 

numpy.searchsorted(a, v, side=SIDE.RIGHT) 

Ich denke, es ist nicht wert, aber auch hier ist es eine Frage des Geschmacks.

[update]

Stefan einen fairen Punkt gemacht:

Sobald die Notwendigkeit, den Wert einer solchen Enum ändern entsteht, Nachschlagen und einen String an vielen Orten zu ersetzen ist nicht meine Vorstellung von Spaß :-)

kann ich sehen, wie schmerzhaft dies in einer Sprache ohne benannte Parameter sein kann - am Beispiel Sie für die Zeichenfolge 'right' zu suchen haben und viele Fehlalarme auslösen. In Python können Sie es auf side='right' eingrenzen.

Natürlich, wenn Sie mit einer Schnittstelle, die bereits eine definierte Menge von enums/Konstanten hat (wie eine externe C-Bibliothek) dann ja, die bestehenden Konventionen imitieren.

3

Ich denke, Enums sind sicherer, vor allem für größere Systeme mit mehreren Entwicklern.

Sobald die Notwendigkeit, den Wert einer solchen Enum ändern entsteht, Nachschlagen und einen String an vielen Orten zu ersetzen ist nicht meine Vorstellung von Spaß :-)

Die wichtigsten Kriterien IMHO ist die Nutzung: für die Verwendung in einem Modul oder sogar einem Paket scheint eine Zeichenfolge in Ordnung zu sein, in einer öffentlichen API würde ich enums bevorzugen.

1

Ich bevorzuge Strings zum Debuggen. ein Objekt wie

side=1, opt_type=0, order_type=6 

vergleichen

side='BUY', opt_type='PUT', order_type='FILL_OR_KILL' 

Ich mag "Aufzählungen" auch dann, wenn die Werte Strings sind:

class Side(object): 
    BUY = 'BUY' 
    SELL = 'SELL' 
    SHORT = 'SHORT' 
1

Python Streng genommen Aufzählungen nicht haben - oder zumindest nicht vor v3.4

https://docs.python.org/3/library/enum.html

Ich bevorzuge es, Ihr Beispiel als Programmierer definierten Konstanten zu denken.

In argparse hat ein Satz von Konstanten String-Werte. Während der Code die Konstantennamen verwendet, verwenden Benutzer häufiger die Strings.

e.g. argparse.ZERO_OR_MORE = '*' 
arg.parse.OPTIONAL = '?' 

numpy einer der älteren 3rd-Party-Pakete (zumindest seine Wurzeln wie numeric sind). String-Werte sind häufiger als Enums. In der Tat kann ich nicht an irgendwelche Enums denken (wie Sie sie definieren).