Recuerde que en Python queremos usar "escribir pato". Entonces, cualquier cosa que actúe como una lista puede tratarse como una lista. Por lo tanto, no verifique el tipo de lista, solo vea si actúa como una lista.
Pero las cadenas también actúan como una lista, y a menudo eso no es lo que queremos. ¡Hay momentos en que incluso es un problema! Por lo tanto, verifique explícitamente una cadena, pero luego use la escritura de pato.
Aquí hay una función que escribí por diversión. Es una versión especial de repr()
que imprime cualquier secuencia entre paréntesis angulares ('<', '>').
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
Esto es limpio y elegante, en general. ¿Pero qué hace ese isinstance()
cheque allí? Eso es una especie de truco. Pero es esencial.
Esta función se llama recursivamente sobre cualquier cosa que actúe como una lista. Si no manejáramos la cadena especialmente, entonces sería tratada como una lista y dividiría un carácter a la vez. Pero entonces la llamada recursiva trataría de tratar a cada personaje como una lista, ¡y funcionaría! ¡Incluso una cadena de un carácter funciona como una lista! La función seguiría llamándose recursivamente hasta que se desborde la pila.
Las funciones como esta, que dependen de cada llamada recursiva que desglosa el trabajo a realizar, tienen que ser cadenas de casos especiales, porque no puede dividir una cadena por debajo del nivel de una cadena de un carácter, e incluso una La cadena de caracteres actúa como una lista.
Nota: la try
/ except
es la forma más limpia de expresar nuestras intenciones. Pero si este código fuera de alguna manera crítico en el tiempo, podríamos reemplazarlo con algún tipo de prueba para ver si arg
es una secuencia. En lugar de probar el tipo, probablemente deberíamos probar los comportamientos. Si tiene un .strip()
método, es una cadena, así que no lo considere una secuencia; de lo contrario, si es indexable o iterable, es una secuencia:
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)
EDITAR: Originalmente escribí lo anterior con un cheque __getslice__()
pero noté que en la collections
documentación del módulo, el método interesante es __getitem__()
; esto tiene sentido, así es como indizas un objeto. Eso parece más fundamental que __getslice__()
eso, cambié lo anterior.