Das Prüfelement ist im Array vorhanden

70

In PHP gibt es eine Funktion, die aufgerufen wird isset(), um zu überprüfen, ob etwas (wie ein Array-Index) vorhanden ist und einen Wert hat. Wie wäre es mit Python?

Ich muss dies für Arrays verwenden, da manchmal "IndexError: Listenindex außerhalb des Bereichs" angezeigt wird.

Ich denke, ich könnte versuchen / fangen, aber das ist ein letzter Ausweg.

Jonny
quelle
2
EAFP: Es ist einfacher, um Vergebung zu bitten, als um Erlaubnis zu bitten.
NullUserException
4
Ihre Frage fragt nach PHP-Arrays (die in Python ungefähr Wörterbücher sind), aber Ihre Fehlermeldung verweist auf eine Listenoperation. Ein Codebeispiel würde wahrscheinlich die Verwirrung beseitigen.
David K. Hess
1
Auch: "letzter Ausweg". "Last Revert" ist etwas ganz anderes.
Amadan
Die Sache ist, dass ich ein Skript geschrieben habe, um eine aus CSV exportierte Google Docs-Tabellenmatrix in etwas anderes zu konvertieren. Wenn die letzte (ganz rechts) Spalte leer war, ignorierte Google manchmal das letzte Komma, das die letzte Spalte angibt.
Jonny

Antworten:

113

Schauen Sie, bevor Sie springen ( LBYL ):

if idx < len(array):
    array[idx]
else:
    # handle this

Es ist einfacher, um Vergebung zu bitten als um Erlaubnis ( EAFP ):

try:
    array[idx]
except IndexError:
    # handle this

In Python scheint EAFP der beliebteste und bevorzugte Stil zu sein. Es ist im Allgemeinen zuverlässiger und vermeidet eine ganze Klasse von Fehlern (Überprüfungszeitpunkt gegenüber Verwendungszeitpunkt). Wenn alle anderen Dinge gleich sind, wird die try/ except-Version empfohlen - sehen Sie es nicht als "letzten Ausweg".

Dieser Auszug stammt aus den oben verlinkten offiziellen Dokumenten und bestätigt die Verwendung von try / mit Ausnahme der Flusskontrolle:

Dieser übliche Python-Codierungsstil setzt die Existenz gültiger Schlüssel oder Attribute voraus und fängt Ausnahmen ab, wenn sich die Annahme als falsch herausstellt. Dieser saubere und schnelle Stil zeichnet sich durch das Vorhandensein vieler Try-and-Except-Aussagen aus.

wim
quelle
Manchmal möchten Sie nur herausfinden, ob ein Index vorhanden ist oder um welchen Index es sich handelt (Python fehlt natürlich eine switch-Anweisung). Ich bin mir auch nicht sicher, ob dies eine Rennbedingung ist, aber ich bin kein Experte. Ist das nicht eine Rennbedingung, wenn der Akt, etwas zu tun, Potenzial für eine Art Looping-Wahnsinn erzeugt? Wenn ich nur überprüfe, ob ein Index vorhanden ist, sollte dies die Race-Iness der Threads nicht beeinflussen. Ich denke, meine Aktionen nach der Überprüfung könnten sich auf andere Threads auswirken.
Ekeyser
1
Andererseits (OTOH) ist EAFP problematisch, da es das Durchlaufen des Aufrufstapels beinhaltet, wenn ein Fehler auftritt.
Darth Egregious
48

EAFP gegen LBYL

Ich verstehe Ihr Dilemma, aber Python ist kein PHP und der Codierungsstil, der als einfacher um Vergebung zu bitten als um Erlaubnis (oder kurz EAFP ) bekannt ist, ist ein gängiger Codierungsstil in Python .

Siehe Quelle (aus der Dokumentation ):

EAFP - Einfacher um Vergebung zu bitten als um Erlaubnis. Dieser übliche Python-Codierungsstil setzt die Existenz gültiger Schlüssel oder Attribute voraus und fängt Ausnahmen ab, wenn sich die Annahme als falsch herausstellt. Dieser saubere und schnelle Stil zeichnet sich durch das Vorhandensein vieler Try-and-Except-Aussagen aus. Die Technik steht im Gegensatz zum LBYL-Stil, der vielen anderen Sprachen wie C gemeinsam ist.

Grundsätzlich ist die Verwendung von try-catch-Anweisungen hier also nicht das letzte Mittel. es ist eine übliche Praxis .

"Arrays" in Python

PHP hat assoziative und nicht assoziative Arrays, Python hat Listen, Tupel und Wörterbücher. Listen ähneln nicht assoziativen PHP-Arrays, Wörterbücher ähneln assoziativen PHP-Arrays.

Wenn Sie überprüfen möchten, ob "Schlüssel" in "Array" vorhanden ist, müssen Sie zuerst angeben, um welchen Typ in Python es sich handelt, da sie unterschiedliche Fehler auslösen, wenn der "Schlüssel" nicht vorhanden ist:

>>> l = [1,2,3]
>>> l[4]

Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    l[4]
IndexError: list index out of range
>>> d = {0: '1', 1: '2', 2: '3'}
>>> d[4]

Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    d[4]
KeyError: 4

Und wenn Sie den EAFP-Codierungsstil verwenden, sollten Sie diese Fehler nur entsprechend abfangen.

LBYL-Codierungsstil - Überprüfung der Existenz von Indizes

Wenn Sie darauf bestehen, den LBYL-Ansatz zu verwenden, sind dies Lösungen für Sie:

  • Für Listen überprüfen Sie einfach die Länge und wenn possible_index < len(your_list), dann your_list[possible_index]existiert, sonst nicht:

    >>> your_list = [0, 1, 2, 3]
    >>> 1 < len(your_list) # index exist
    True
    >>> 4 < len(your_list) # index does not exist
    False
    
  • Für Wörterbücher können Sie ein inSchlüsselwort verwenden, und wenn possible_index in your_dict, dann your_dict[possible_index]existiert es, sonst nicht:

    >>> your_dict = {0: 0, 1: 1, 2: 2, 3: 3}
    >>> 1 in your_dict # index exists
    True
    >>> 4 in your_dict # index does not exist
    False
    

Hat es geholfen?

Tadeck
quelle
Gute Antwort. Gibt es einen Grund, warum undefinierte Eigenschaften oder Indizes in Python einfach nicht als undefinedoder bool zurückgegeben werden false? Andere Sprachdolmetscher kehren zu diesen Ereignissen zurück und ich bin nur neugierig, warum Python dies nicht tut.
65Fbef05
@ 65Fbef05: Ich glaube, es ist eine Designentscheidung, aber tatsächlich können Sie dies my_dict.get('some_index', False)zum Beispiel tun , sodass Sie nicht so eingeschränkt sind. Sollte Python auch wirklich zurückkehren, Falsewenn Sie versuchen, einen Eintrag aus dem Wörterbuch zu erhalten, wenn dieser nicht vorhanden ist? Ich glaube nein, weil es schwierig wäre, das Problem im Code zu finden, wenn das Speichern Falseund Nicht-Speichern von etwas für einen bestimmten Schlüssel das gleiche Ergebnis liefert. Ich halte dies für eine gute Idee, Fehler zu werfen, wenn etwas, das Sie wollten, nicht hier ist und Sie nicht ausdrücklich gesagt haben, dass Sie sich mit einem solchen Fall befassen sollen (z. B. durch Verwendung von get()).
Tadeck
1
Ein spezieller Fall, in dem die Rückgabe meiner Meinung nach Falsehilfreicher ist als das Auslösen eines Fehlers, ist, wenn Sie sich nicht sicher sind, ob ein Index vorhanden ist, wie im Fall optionaler CLI-Argumente, bei denen die praktische Ausnahme von Ihrer Anwendungslogik nur auftritt, wenn ein Wert vorhanden ist.
65Fbef05
@ 65Fbef05: Es ist nicht erforderlich, Ausnahmen auszulösen, wenn bestimmte CLI-Argumente vorhanden sind oder nicht. Sie können einfach das argparseModul verwenden . Und ich erinnere mich an keine Sprache, die tatsächlich einen Fehler auslöst, wenn es einen Wert gibt, nach dem sie sucht. Oder ich habe Ihren Kommentar falsch verstanden;) Wie gesagt, Sie können das Standardargument unterstützen, indem Sie etwas Ähnliches verwenden cli_args.get('option1', False).
Tadeck
Ich meinte nicht unbedingt "Fehler werfen", wenn festgestellt wird, dass ein Wert vorhanden ist. Ich meinte mehr oder weniger "etwas anderes machen" als die Standardroutine.
65Fbef05
15
`e` in ['a', 'b', 'c']  # evaluates as False
`b` in ['a', 'b', 'c']  # evaluates as True

EDIT : Mit der Klarstellung, neue Antwort:

Beachten Sie, dass sich PHP-Arrays stark von Pythons unterscheiden und Arrays und Dicts in einer verwirrten Struktur kombinieren. Python-Arrays haben immer Indizes von 0bis len(arr) - 1, sodass Sie überprüfen können, ob Ihr Index in diesem Bereich liegt. try/catchist jedoch eine gute Möglichkeit, dies pythonisch zu tun.

Wenn Sie nach der Hash-Funktionalität von PHP "Arrays" (Pythons dict) fragen , dann steht meine vorherige Antwort immer noch so:

`baz` in {'foo': 17, 'bar': 19}  # evaluates as False
`foo` in {'foo': 17, 'bar': 19}  # evaluates as True
Amadan
quelle
Hm? Ich habe gefragt, ob ein indiziertes Element im Array vorhanden ist, nicht, ob ein Wert im Array vorhanden ist.
Jonny
@Jonny: Dies ist einer der Unterschiede zwischen PHP und Python. Ein PHP-Array ist ein Wörterbuch in Python. In Python hat eine Liste nur ganzzahlige Indizes.
Unholysampler
8

has_key ist schnell und effizient.

Verwenden Sie anstelle eines Arrays einen Hash:

valueTo1={"a","b","c"}

if valueTo1.has_key("a"):
        print "Found key in dictionary"
Arik Harel
quelle
3
AttributeError: 'set' object has no attribute 'has_key'
Alamin
0

Sie können in der Lage sein , die eingebaute Funktion zu benutzen ein dir()ähnliches Verhalten wie PHP zu erzeugen , isset()wie etwas:

if 'foo' in dir():  # returns False, foo is not defined yet.
    pass

foo = 'b'

if 'foo' in dir():  # returns True, foo is now defined and in scope.
   pass

dir()Gibt eine Liste der Namen im aktuellen Bereich zurück. Weitere Informationen finden Sie hier: http://docs.python.org/library/functions.html#dir .

DRH
quelle
0

In Python werden Sie möglicherweise einige Überraschungen erleben, wenn Sie in diesem Fall um Vergebung bitten.

Try-Except ist hier nicht das richtige Paradigma.

Wenn Sie versehentlich negative Indizes erhalten, werden Sie überrascht sein.

Eine bessere Lösung besteht darin, die Testfunktion selbst bereitzustellen:

def index_in_array(M, index):
    return index[0] >= 0 and index[1] >= 0 and index[0]< M.shape[0] and index[1] < M.shape[1]
Ronald van Elburg
quelle