492 Stimmen

Wie kann man prüfen, ob ein Objekt eine Liste oder ein Tupel (aber keine Zeichenkette) ist?

Das ist es, was ich normalerweise tue, um sicherzustellen, dass es sich bei der Eingabe um eine list / tuple - aber nicht ein str . Denn oft bin ich über Bugs gestolpert, bei denen eine Funktion eine str Objekt versehentlich, und die Zielfunktion macht for x in lst unter der Annahme, dass lst ist eigentlich ein list o tuple .

assert isinstance(lst, (list, tuple))

Meine Frage lautet: Gibt es eine bessere Möglichkeit, dies zu erreichen?

14voto

Om Prakash Punkte 2433

Versuchen Sie dies, um die Lesbarkeit und die besten Praktiken zu verbessern:

Python2 - isinstance()

import types
if isinstance(lst, types.ListType) or isinstance(lst, types.TupleType):
    # Do something

Python3 - isinstance()

import typing
if isinstance(lst, typing.List) or isinstance(lst, typing.Tuple):
    # Do something

Ich hoffe, es hilft.

11voto

Robert Rossney Punkte 91100

Im Allgemeinen ist die Tatsache, dass eine Funktion, die über ein Objekt iteriert, sowohl mit Zeichenketten als auch mit Tupeln und Listen funktioniert, eher ein Feature als ein Fehler. Sie haben sicherlich verwenden. isinstance oder sich beim Tippen ducken, um ein Argument zu überprüfen, aber warum sollten Sie?

Das klingt wie eine rhetorische Frage, aber das ist sie nicht. Die Antwort auf die Frage "Warum sollte ich den Typ des Arguments prüfen?" wird wahrscheinlich eine Lösung für das eigentliche Problem vorschlagen, nicht für das vermeintliche Problem. Warum ist es ein Fehler, wenn eine Zeichenkette an die Funktion übergeben wird? Außerdem: Wenn es ein Fehler ist, wenn eine Zeichenkette an diese Funktion übergeben wird, ist es dann auch ein Fehler, wenn eine andere Nicht-Liste/Tupel-Iterable an die Funktion übergeben wird? Warum, oder warum nicht?

Ich denke, dass die häufigste Antwort auf diese Frage sein wird, dass Entwickler, die f("abc") erwarten, dass sich die Funktion so verhält, als hätten sie geschrieben f(["abc"]) . Es gibt wahrscheinlich Umstände, in denen es sinnvoller ist, Entwickler vor sich selbst zu schützen, als den Anwendungsfall der Iteration über die Zeichen in einer Zeichenkette zu unterstützen. Aber ich würde zuerst lange und gründlich darüber nachdenken.

6voto

max Punkte 44579

Dies soll keine direkte Antwort auf die Frage des Auftraggebers sein, aber ich wollte einige damit zusammenhängende Ideen mitteilen.

Ich war sehr an der obigen Antwort von @steveha interessiert, die ein Beispiel zu geben schien, bei dem die Duck-Typisierung zu brechen scheint. Bei näherem Nachdenken deutet sein Beispiel jedoch darauf hin, dass die Duck-Typisierung schwer einzuhalten ist, aber sie tut es no legen nahe, dass str eine besondere Behandlung verdient.

Schließlich ist ein Nicht str Typ (z. B. ein benutzerdefinierter Typ, der einige komplizierte rekursive Strukturen enthält) kann dazu führen, dass @steveha srepr Funktion eine unendliche Rekursion auslösen. Obwohl dies zugegebenermaßen eher unwahrscheinlich ist, können wir diese Möglichkeit nicht ignorieren. Daher sollten wir statt der Sonderkodierung str in srepr sollten wir klären, was wir wollen srepr was zu tun ist, wenn sich eine unendliche Rekursion ergibt.

Ein vernünftiger Ansatz könnte darin bestehen, die Rekursion einfach in srepr der Moment list(arg) == [arg] . Dies würde das Problem mit den folgenden Punkten vollständig lösen str , ohne jegliche isinstance .

Eine wirklich komplizierte rekursive Struktur kann jedoch zu einer Endlosschleife führen, in der list(arg) == [arg] passiert nie. Daher ist die obige Prüfung zwar nützlich, aber nicht ausreichend. Wir brauchen so etwas wie eine harte Grenze für die Rekursionstiefe.

Mein Punkt ist, dass wenn Sie planen, beliebige Argumenttypen zu behandeln, die Behandlung str via duck typing ist viel, viel einfacher als der Umgang mit den allgemeineren Typen, denen man (theoretisch) begegnen kann. Wenn Sie also das Bedürfnis haben, folgende Typen auszuschließen str Instanzen, sollten Sie stattdessen verlangen, dass das Argument eine Instanz eines der wenigen Typen ist, die Sie ausdrücklich angeben.

6voto

Lerner Zhang Punkte 5074

Ich finde eine solche Funktion namens is_sequence in Tensorflow .

def is_sequence(seq):
  """Returns a true if its input is a collections.Sequence (except strings).
  Args:
    seq: an input sequence.
  Returns:
    True if the sequence is a not a string and is a collections.Sequence.
  """
  return (isinstance(seq, collections.Sequence)
and not isinstance(seq, six.string_types))

Und ich habe mich vergewissert, dass es Ihren Bedürfnissen entspricht.

5voto

Moe Punkte 26523

El str Objekt hat keine __iter__ 属性

>>> hasattr('', '__iter__')
False 

damit Sie eine Prüfung durchführen können

assert hasattr(x, '__iter__')

und dies wird auch eine schöne AssertionError auch für jedes andere nicht-iterable Objekt.

Editar: Wie Tim in den Kommentaren erwähnt, funktioniert dies nur in Python 2.x, nicht 3.x

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X