Ich habe Code, der ungefähr so aussieht:
thing_index = thing_list.index(thing)
otherfunction(thing_list, thing_index)
ok, das ist vereinfacht, aber Sie bekommen die Idee. Nun ist thing
möglicherweise nicht wirklich in der Liste. In diesem Fall möchte ich -1 als thing_index
übergeben. In anderen Sprachen würden Sie erwarten, dass index()
zurückkehrt, wenn das Element nicht gefunden wurde. Tatsächlich wirft es eine ValueError
.
Ich könnte das machen:
try:
thing_index = thing_list.index(thing)
except ValueError:
thing_index = -1
otherfunction(thing_list, thing_index)
Aber das fühlt sich schmutzig an und ich weiß nicht, ob ValueError
aus einem anderen Grund angehoben werden könnte. Ich habe die folgende Lösung auf der Grundlage von Generatorfunktionen gefunden, die jedoch etwas komplex erscheint:
thing_index = ( [(i for i in xrange(len(thing_list)) if thing_list[i]==thing)] or [-1] )[0]
Gibt es einen saubereren Weg, um dasselbe zu erreichen? Nehmen wir an, die Liste ist nicht sortiert.
Es ist nichts "schmutzig" bei der Verwendung der try-except-Klausel. Dies ist der pythonische Weg. ValueError
wird nur von der .index
-Methode ausgelöst, da dies der einzige Code ist, den Sie dort haben!
Um den Kommentar zu beantworten:
In Python ist es ist einfacher, um Vergebung zu bitten, als um Erlaubnis zu bitten philosophie ist etabliert, und noindex
löst diese Art Fehler nicht für andere Probleme aus. Nicht, dass mir was einfällt.
thing_index = thing_list.index(elem) if elem in thing_list else -1
Eine Linie. Einfach. Keine Ausnahmen.
Der dict
-Typ hat eine get
-Funktion . Wenn der Schlüssel nicht im Wörterbuch vorhanden ist, ist das 2. Argument für get
der Wert, den es zurückgeben soll. Ebenso gibt es setdefault
, das den Wert in der dict
zurückgibt, wenn der Schlüssel vorhanden ist. Andernfalls wird der Wert entsprechend Ihrem Standardparameter festgelegt und der Standardparameter zurückgegeben.
Sie könnten den Typ list
erweitern, um eine getindexdefault
-Methode zu erhalten.
class SuperDuperList(list):
def getindexdefault(self, elem, default):
try:
thing_index = self.index(elem)
return thing_index
except ValueError:
return default
Was könnte dann verwendet werden:
mylist = SuperDuperList([0,1,2])
index = mylist.getindexdefault( 'asdf', -1 )
Es ist nichts falsch mit Ihrem Code, der ValueError
verwendet. Hier ist noch ein Einzeiler, wenn Sie Ausnahmen vermeiden möchten:
thing_index = next((i for i, x in enumerate(thing_list) if x == thing), -1)
Diese Ausgabe ist eine Sprachphilosophie. In Java zum Beispiel gab es immer die Tradition, dass Ausnahmen eigentlich nur in "Ausnahmefällen" verwendet werden sollten, in denen Fehler aufgetreten sind, und nicht für flow control . Am Anfang war dies aus Gründen der Performance, da Java-Ausnahmen langsam waren, aber jetzt ist dies der akzeptierte Stil.
Im Gegensatz dazu hat Python immer Ausnahmen verwendet, um auf einen normalen Programmablauf hinzuweisen, wie das Erhöhen einer ValueError
, wie wir hier besprechen. Es gibt nichts "Dreckiges" im Python-Stil und es gibt viele weitere, aus denen das kam. Ein noch häufigeres Beispiel ist StopIteration
exception , das von der next()
-Methode eines Iterators ausgelöst wird, um zu signalisieren, dass keine weiteren Werte vorhanden sind.
Was ist mit diesem:
otherfunction(thing_collection, thing)
Anstatt etwas so implementierungsabhängiges wie einen Listenindex in einer Funktionsschnittstelle bereitzustellen, übergeben Sie die Sammlung und die Sache und lassen andere Funktionen sich mit dem "Test auf Mitgliedschaft" befassen. Wenn eine andere Funktion als sammlungsunabhängig geschrieben wird, beginnt sie wahrscheinlich mit:
if thing in thing_collection:
... proceed with operation on thing
was funktionieren wird, wenn thing_collection eine Liste, ein Tuple, ein Set oder ein Dikt ist.
Dies ist möglicherweise klarer als:
if thing_index != MAGIC_VALUE_INDICATING_NOT_A_MEMBER:
dies ist der Code, den Sie bereits in einer anderen Funktion haben.
Wenn Sie dies häufig tun, ist es besser, es in einer Hilfsfunktion wegzurennen:
def index_of(val, in_list):
try:
return in_list.index(val)
except ValueError:
return -1
Ich habe das gleiche Problem mit der ".index ()" - Methode in Listen. Ich habe kein Problem mit der Tatsache, dass es eine Ausnahme auslöst, aber ich bin absolut nicht einverstanden mit der Tatsache, dass es sich um einen nicht beschreibenden ValueError handelt. Ich könnte verstehen, ob es ein IndexError gewesen wäre.
Ich kann sehen, warum die Rückgabe von "-1" ebenfalls ein Problem darstellt, da es sich um einen gültigen Index in Python handelt. Aber realistisch erwarte ich nie, dass eine ".index ()" - Methode eine negative Zahl zurückgibt.
Hier geht ein Einzeiler (ok, es ist eine ziemlich lange Zeile ...), geht die Liste genau einmal durch und gibt "Keine" zurück, wenn der Gegenstand nicht gefunden wird. Es wäre trivial, es umzuschreiben, um -1 zurückzugeben, falls Sie dies wünschen.
indexOf = lambda list, thing: \
reduce(lambda acc, (idx, elem): \
idx if (acc is None) and elem == thing else acc, list, None)
Wie benutzt man:
>>> indexOf([1,2,3], 4)
>>>
>>> indexOf([1,2,3], 1)
0
>>>
Was ist mit so:
temp_inx = (L + [x]).index(x)
inx = temp_inx if temp_inx < len(L) else -1
Was ist damit ???? :
li = [1,2,3,4,5] # create list
li = dict(Zip(li,range(len(li)))) # convert List To Dict
print( li ) # {1: 0, 2: 1, 3: 2, 4:3 , 5: 4}
li.get(20) # None
li.get(1) # 0