O que exatamente significa "iterável" em Python?
Primeiro quero esclarecer, NÃO estou perguntando o que é "iterador".
É assim que o termo "iterável" é definido no Pythondoc:
iterável
Um objeto capaz de retornar seus membros um de cada vez. Exemplos de iteráveis incluem todos os tipos de sequência (como lista, str e tupla) e alguns tipos que não são de sequência, como dict, objetos de arquivo e objetos de qualquer classe, definidos com um__iter __ () ou __getitem __ () método. Os iteráveis podem ser usados em um loop for e em muitos outros lugares em que uma sequência é necessária (zip (), mapa (), ...). Quando um objeto iterável é passado como argumento para a função interna iter (), ele retorna um iterador para o objeto. Esse iterador é bom para uma passagem sobre o conjunto de valores. Ao usar iterables, geralmente não é necessário chamar iter () ou lidar com objetos iteradores. A instrução for faz isso automaticamente para você, criando uma variável temporária sem nome para manter o iterador pela duração do loop. Consulte também iterador, sequência e gerador.
Comooutras pessoas sugeriram, usandoisinstance(e, collections.Iterable)
é a maneira mais pitônica de verificar se um objeto é iterável.
Então eu fiz alguns testes com o Python 3.4.3:
from collections.abc import Iterable
class MyTrain:
def __getitem__(self, index):
if index > 3:
raise IndexError("that's enough!")
return index
for name in MyTrain():
print(name) # 0, 1, 2, 3
print(isinstance(MyTrain(), Iterable)) # False
O resultado é bastante estranho:MyTrain
definiu__getitem__
, mas não é considerado um objeto iterável, sem mencionar que é capaz de retornar um número de cada vez.
Então eu removi__getitem__
e adicionou o__iter__
método:
from collections.abc import Iterable
class MyTrain:
def __iter__(self):
print("__iter__ called")
pass
print(isinstance(MyTrain(), Iterable)) # True
for name in MyTrain():
print(name) # TypeError: iter() returned non-iterator of type 'NoneType'
Agora é considerado como um objeto iterável "verdadeiro", apesar de não poder produzir nada durante a iteração.
Entendi mal alguma coisa ou a documentação está incorreta?