Lembre-se de que, em Python, queremos usar "digitação de pato". Portanto, qualquer coisa que atue como uma lista pode ser tratada como uma lista. Portanto, não verifique o tipo de uma lista, apenas veja se ela funciona como uma lista.
Mas as strings também funcionam como uma lista, e muitas vezes não é isso que queremos. Há momentos em que é até um problema! Portanto, verifique explicitamente se há uma string, mas use a digitação de pato.
Aqui está uma função que escrevi por diversão. É uma versão especial repr()
que imprime qualquer sequência entre colchetes 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
Isso é limpo e elegante, em geral. Mas o que esse isinstance()
cheque está fazendo lá? Isso é meio que um hack. Mas é essencial.
Essa função se chama recursivamente em qualquer coisa que atue como uma lista. Se não tratássemos a string especialmente, ela seria tratada como uma lista e dividiria um caractere de cada vez. Mas então a chamada recursiva tentaria tratar cada caractere como uma lista - e funcionaria! Mesmo uma cadeia de um caractere funciona como uma lista! A função continuaria se chamando recursivamente até o estouro da pilha.
Funções como esta, que dependem de cada chamada recursiva, dividindo o trabalho a ser realizado, têm cadeias de casos especiais - porque você não pode dividir uma cadeia abaixo do nível de uma cadeia de um caractere e até uma -caracter string atua como uma lista.
Nota: a try
/ except
é a maneira mais limpa de expressar nossas intenções. Mas se esse código for de alguma forma crítico em termos de tempo, podemos substituí-lo por algum tipo de teste para ver se arg
é uma sequência. Em vez de testar o tipo, provavelmente devemos testar comportamentos. Se ele tem um .strip()
método, é uma string, então não considere uma sequência; caso contrário, se for indexável ou iterável, é uma sequência:
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)
EDIT: Eu escrevi originalmente o acima com uma verificação, __getslice__()
mas notei que na collections
documentação do módulo, o método interessante é __getitem__()
; isso faz sentido, é assim que você indexa um objeto. Isso parece mais fundamental do que __getslice__()
eu mudei o acima.