Denken Sie daran, dass wir in Python "Duck Typing" verwenden möchten. Alles, was sich wie eine Liste verhält, kann als Liste behandelt werden. Überprüfen Sie also nicht den Typ einer Liste, sondern prüfen Sie, ob sie sich wie eine Liste verhält.
Aber Strings wirken auch wie eine Liste, und oft ist das nicht das, was wir wollen. Es gibt Zeiten, in denen es sogar ein Problem ist! Suchen Sie also explizit nach einer Zeichenfolge, verwenden Sie dann jedoch die Ententypisierung.
Hier ist eine Funktion, die ich zum Spaß geschrieben habe. Es ist eine spezielle Version repr()
, die jede Sequenz in spitzen Klammern ('<', '>') druckt.
def srepr(arg):
if isinstance(arg, basestring): # Python 3: isinstance(arg, str)
return repr(arg)
try:
return '<' + ", ".join(srepr(x) for x in arg) + '>'
except TypeError: # catch when for loop fails
return repr(arg) # not a sequence so just return repr
Dies ist insgesamt sauber und elegant. Aber was macht dieser isinstance()
Scheck dort? Das ist eine Art Hack. Aber es ist wichtig.
Diese Funktion ruft sich rekursiv für alles auf, was sich wie eine Liste verhält. Wenn wir die Zeichenfolge nicht speziell behandeln würden, würde sie wie eine Liste behandelt und jeweils ein Zeichen aufgeteilt. Aber dann würde der rekursive Aufruf versuchen, jedes Zeichen als Liste zu behandeln - und es würde funktionieren! Sogar eine einstellige Zeichenfolge funktioniert als Liste! Die Funktion ruft sich selbst rekursiv auf, bis der Stapel überläuft.
Funktionen wie diese, die von jedem rekursiven Aufruf abhängen, der die zu erledigende Arbeit aufschlüsselt, müssen Sonderzeichenfolgen enthalten - da Sie eine Zeichenfolge nicht unter der Ebene einer Zeichenfolge mit einem Zeichen und sogar einer Zeichenfolge aufteilen können -character string verhält sich wie eine Liste.
Hinweis: Das try
/ except
ist der sauberste Weg, um unsere Absichten auszudrücken. Wenn dieser Code jedoch zeitkritisch wäre, möchten wir ihn möglicherweise durch eine Art Test ersetzen, um festzustellen, ob arg
es sich um eine Sequenz handelt. Anstatt den Typ zu testen, sollten wir wahrscheinlich das Verhalten testen. Wenn es eine .strip()
Methode hat, ist es eine Zeichenfolge. Betrachten Sie sie also nicht als Sequenz. Andernfalls ist es eine Sequenz, wenn es indizierbar oder iterierbar ist:
def is_sequence(arg):
return (not hasattr(arg, "strip") and
hasattr(arg, "__getitem__") or
hasattr(arg, "__iter__"))
def srepr(arg):
if is_sequence(arg):
return '<' + ", ".join(srepr(x) for x in arg) + '>'
return repr(arg)
BEARBEITEN: Ich habe das Obige ursprünglich mit einem Check für geschrieben, __getslice__()
aber ich habe festgestellt, dass in der collections
Moduldokumentation die interessante Methode ist __getitem__()
; Das macht Sinn, so indizieren Sie ein Objekt. Das scheint grundlegender zu sein, __getslice__()
also habe ich das oben Gesagte geändert.