Qual é a definição mais básica de "iterável", "iterador" e "iteração" no Python?
Eu li várias definições, mas não consigo identificar o significado exato, pois ele ainda não se encaixa.
Alguém pode me ajudar com as 3 definições em termos leigos?
Qual é a definição mais básica de "iterável", "iterador" e "iteração" no Python?
Eu li várias definições, mas não consigo identificar o significado exato, pois ele ainda não se encaixa.
Alguém pode me ajudar com as 3 definições em termos leigos?
Respostas:
Iteração é um termo geral para pegar cada item de algo, um após o outro. Sempre que você usa um loop, explícito ou implícito, para examinar um grupo de itens, é iteração.
No Python, iterável e iterador têm significados específicos.
Um iterável é um objeto que possui um __iter__método que retorna um iterador ou que define um __getitem__método que pode receber índices seqüenciais começando do zero (e gera um IndexErrorquando os índices não são mais válidos). Portanto, um iterável é um objeto do qual você pode obter um iterador .
Um iterador é um objeto com um método next(Python 2) ou __next__(Python 3).
Sempre que você usa um forloop, ou mapuma compreensão de lista etc. no Python, o nextmétodo é chamado automaticamente para obter cada item do iterador , passando pelo processo de iteração .
Um bom lugar para começar a aprender seria a seção de iteradores do tutorial e a seção de tipos de iteradores da página de tipos padrão . Depois de entender o básico, tente a seção de iteradores do HOWTO de Programação Funcional .
__len__estaria necessariamente vinculado à iteração? Como saber o tamanho de algo o ajudaria a interagir com ele?
__getitem__ .
{'a': 'hi', 'b': 'bye'}possui comprimento 2, mas não pode ser indexado por 0, 1 ou 2.
__iter__método. Eu acho que jlh está se referindo a objetos iteráveis especificamente porque eles definem: "um __getitem__método que pode receber índices seqüenciais a partir do zero".
Aqui está a explicação que eu uso nas aulas de Python:
Um ITERABLE é:
for x in iterable: ...ouiter()retornará um ITERATOR: iter(obj)ou__iter__ que retorna um ITERATOR novo ou pode ter um __getitem__método adequado para pesquisa indexada.Um ITERATOR é um objeto:
__next__ método que:
StopIteration__iter__método que retorna self).Notas:
__next__ método no Python 3 está escrito nextno Python 2 enext() chama esse método no objeto passado para ele.Por exemplo:
>>> s = 'cat' # s is an ITERABLE
# s is a str object that is immutable
# s has no state
# s has a __getitem__() method
>>> t = iter(s) # t is an ITERATOR
# t has state (it starts by pointing at the "c"
# t has a next() method and an __iter__() method
>>> next(t) # the next() function returns the next value and advances the state
'c'
>>> next(t) # the next() function returns the next value and advances
'a'
>>> next(t) # the next() function returns the next value and advances
't'
>>> next(t) # next() raises StopIteration to signal that iteration is complete
Traceback (most recent call last):
...
StopIteration
>>> iter(t) is t # the iterator is self-iterable
forloops, e o primeiro marcador é sobre "looping over". Você poderia resolver estes?
iter()" como "qualquer coisa que você pode passar para iter()"
As respostas acima são ótimas, mas, como a maior parte do que eu vi, não enfatize distinção o suficiente para pessoas como eu.
Além disso, as pessoas tendem a ficar "muito pitonicas" colocando definições como "X é um objeto que possui __foo__()método" antes. Tais definições estão corretas - elas se baseiam na filosofia de digitação de patos, mas o foco nos métodos tende a ficar mais claro quando se tenta entender o conceito em sua simplicidade.
Então eu adiciono minha versão.
Em linguagem natural,
Em Python,
iterável é um objeto que é, bem, iterável, que simplesmente coloca, significa que ele pode ser usado na iteração, por exemplo, com um forloop. Quão? Usando o iterador . Eu vou explicar abaixo.
... enquanto o iterador é um objeto que define como realmente fazer a iteração - especificamente qual é o próximo elemento. É por isso que deve ter
next()método.
Os iteradores também são iteráveis, com a distinção de que seu __iter__()método retorna o mesmo objeto ( self), independentemente de seus itens terem ou não sido consumidos por chamadas anteriores para next().
Então, o que o intérprete Python pensa quando vê uma for x in obj:declaração?
Olha, um
forlaço. Parece um trabalho para um iterador ... Vamos pegar um. ... Tem esseobjcara, então vamos perguntar a ele."Sr.
obj, você tem seu iterador?" (... chamaiter(obj), que chamaobj.__iter__(), que felizmente distribui um novo iterador brilhante_i.)OK, foi fácil ... Vamos começar a iterar então. (
x = _i.next()...x = _i.next()...)
Como o Sr. objobteve sucesso neste teste (com um método retornando um iterador válido), recompensamos-o com o adjetivo: agora você pode chamá-lo de "Sr. iterável obj".
No entanto, em casos simples, você normalmente não se beneficia de ter o iterador e iterável separadamente. Portanto, você define apenas um objeto, que também é seu próprio iterador. (O Python realmente não se importa com o fato de que a _idistribuição objnão foi tão brilhante, mas apenas a objprópria).
É por isso que na maioria dos exemplos que eu vi (e o que estava me confundindo repetidamente), você pode ver:
class IterableExample(object):
def __iter__(self):
return self
def next(self):
pass
ao invés de
class Iterator(object):
def next(self):
pass
class Iterable(object):
def __iter__(self):
return Iterator()
Há casos, no entanto, quando você pode se beneficiar da separação do iterador do iterável, como quando você deseja ter uma linha de itens, mas mais "cursores". Por exemplo, quando você deseja trabalhar com os elementos "atual" e "próximo", é possível ter iteradores separados para ambos. Ou vários threads extraídos de uma lista enorme: cada um pode ter seu próprio iterador para percorrer todos os itens. Veja @ Raymond's e @ glglgl's respostas de acima.
Imagine o que você poderia fazer:
class SmartIterableExample(object):
def create_iterator(self):
# An amazingly powerful yet simple way to create arbitrary
# iterator, utilizing object state (or not, if you are fan
# of functional), magic and nuclear waste--no kittens hurt.
pass # don't forget to add the next() method
def __iter__(self):
return self.create_iterator()
Notas:
Vou repetir novamente: o iterador não é iterável . O iterador não pode ser usado como uma "fonte" no forloop. O que o forloop precisa principalmente é __iter__()
(que retorna algo com next()).
Obviamente, esse fornão é o único loop de iteração; portanto, acima também se aplica a outras construções ( while...).
O iterador next()pode lançar StopIteration para interromper a iteração. No entanto, ele não precisa iterar para sempre ou usar outros meios.
No "processo de pensamento" acima, _iele realmente não existe. Eu inventei esse nome.
Há uma pequena alteração no Python 3.x: o next()método (não o incorporado) agora deve ser chamado __next__(). Sim, deveria ter sido assim o tempo todo.
Você também pode pensar assim: iterável possui os dados, o iterador puxa o próximo item
Isenção de responsabilidade: eu não sou desenvolvedor de nenhum intérprete Python, então não sei realmente o que o intérprete "pensa". As reflexões acima são apenas uma demonstração de como eu entendo o tópico de outras explicações, experimentos e experiências da vida real de um novato em Python.
forloop precisa de um iterador ("Olha, um loop for. Parece um trabalho para um iterador ... Vamos pegar um."). Mas então você diz nas notas no final que "O iterador não pode ser usado como fonte em um forloop" ...?
passo código para essas nextdefinições? Suponho que você apenas queira dizer que alguém precisa implementar uma maneira de obter a próxima, já que a próxima deve retornar alguma coisa.
passé para , depois de tudo.)
pass, acho que está lá por razões sintáticas. Acabei de encontrar as respostas no objeto de reticências que são bastante interessantes: você pode usar ...para indicar um bloco "todo mais tarde". NotImplementedtambém está disponível.
forloop '. Entendi a sua resposta e, caso contrário, gostaria, mas acho que se beneficiaria disso.
Um iterável é um objeto que possui um __iter__()método. Ele pode ser repetido várias vezes, como list()s e tuple()s.
Um iterador é o objeto que itera. Ele é retornado por um __iter__()método, retorna por meio de seu próprio __iter__()método e possui um next()método ( __next__()na versão 3.x).
A iteração é o processo de chamar isso de next()resp. __next__()até que aumente StopIteration.
Exemplo:
>>> a = [1, 2, 3] # iterable
>>> b1 = iter(a) # iterator 1
>>> b2 = iter(a) # iterator 2, independent of b1
>>> next(b1)
1
>>> next(b1)
2
>>> next(b2) # start over, as it is the first call to b2
1
>>> next(b1)
3
>>> next(b1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>> b1 = iter(a) # new one, start over
>>> next(b1)
1
Iterable.
Iteratoré sempre Iterablee é seu Iterator, duas chamadas de iter()não dão necessariamente duas Iterators independentes .
Aqui está minha cábula:
sequence
+
|
v
def __getitem__(self, index: int):
+ ...
| raise IndexError
|
|
| def __iter__(self):
| + ...
| | return <iterator>
| |
| |
+--> or <-----+ def __next__(self):
+ | + ...
| | | raise StopIteration
v | |
iterable | |
+ | |
| | v
| +----> and +-------> iterator
| ^
v |
iter(<iterable>) +----------------------+
|
def generator(): |
+ yield 1 |
| generator_expression +-+
| |
+-> generator() +-> generator_iterator +-+
Quiz: Você vê como ...
__iter__() método de pode ser implementado como um gerador?__next__método não é necessariamente um iterador?Respostas:
__iter__método Ter __iter__é suficiente para ser iterável. Portanto, todo iterador é iterável.Quando __iter__é chamado, ele deve retornar um iterador ( return <iterator>no diagrama acima). Chamar um gerador retorna um iterador de gerador, que é um tipo de iterador.
class Iterable1:
def __iter__(self):
# a method (which is a function defined inside a class body)
# calling iter() converts iterable (tuple) to iterator
return iter((1,2,3))
class Iterable2:
def __iter__(self):
# a generator
for i in (1, 2, 3):
yield i
class Iterable3:
def __iter__(self):
# with PEP 380 syntax
yield from (1, 2, 3)
# passes
assert list(Iterable1()) == list(Iterable2()) == list(Iterable3()) == [1, 2, 3]Aqui está um exemplo:
class MyIterable:
def __init__(self):
self.n = 0
def __getitem__(self, index: int):
return (1, 2, 3)[index]
def __next__(self):
n = self.n = self.n + 1
if n > 3:
raise StopIteration
return n
# if you can iter it without raising a TypeError, then it's an iterable.
iter(MyIterable())
# but obviously `MyIterable()` is not an iterator since it does not have
# an `__iter__` method.
from collections.abc import Iterator
assert isinstance(MyIterable(), Iterator) # AssertionError__iter__método. Você pode elaborar os pontos 2 e 3 editando esta resposta
__iter__()retorna um iterador. Um gerador é um iterador, portanto, pode ser usado para essa finalidade. re 3 .: Só posso adivinhar aqui, mas acho que se __iter__()está faltando ou não retorna self, não é um iterador, porque o iterador __iter__()precisa retornar self.
Não sei se ajuda alguém, mas sempre gosto de visualizar conceitos na minha cabeça para melhor entendê-los. Então, como eu tenho um filho pequeno, visualizo o conceito iterável / iterador com tijolos e papel branco.
Suponha que estejamos no quarto escuro e no chão tenhamos tijolos para o meu filho. Tijolos de diferentes tamanhos, cores, não importam agora. Suponha que tenhamos 5 tijolos como esses. Esses 5 tijolos podem ser descritos como um objeto - digamos, kit de tijolos . Podemos fazer muitas coisas com este kit de tijolos - podemos pegar um e depois o segundo e o terceiro, trocar de lugar dos tijolos, colocar o primeiro tijolo acima do segundo. Podemos fazer muitos tipos de coisas com elas. Portanto, este kit de tijolos é um objeto ou sequência iterável , pois podemos percorrer cada tijolo e fazer algo com ele. Só podemos fazer isso como meu filho pequeno - podemos brincar com um tijolo de cada vez, . Então, novamente, eu me imagino este kit de tijolos para ser umiterável .
Agora lembre-se de que estamos no quarto escuro. Ou quase escuro. O fato é que não vemos claramente esses tijolos, que cor são, que forma etc. Portanto, mesmo se queremos fazer algo com eles - também conhecido como iterar através deles - não sabemos realmente o que e como, porque é muito escuro.
O que podemos fazer é próximo ao primeiro tijolo - como elemento de um kit de tijolos -, podemos colocar um pedaço de papel branco fluorescente para vermos onde está o primeiro elemento de tijolo. E cada vez que tiramos um tijolo de um kit, substituímos o pedaço de papel branco por outro próximo para poder vê-lo no quarto escuro. Este pedaço de papel branco não passa de um iterador . É um objeto também . Mas um objeto com o que podemos trabalhar e brincar com elementos do nosso iterável objeto - kit de tijolos.
A propósito, isso explica meu erro inicial quando tentei o seguinte em um IDLE e obtive um TypeError:
>>> X = [1,2,3,4,5]
>>> next(X)
Traceback (most recent call last):
File "<pyshell#19>", line 1, in <module>
next(X)
TypeError: 'list' object is not an iterator
A lista X aqui era o nosso kit de tijolos, mas NÃO era um pedaço de papel branco. Eu precisava encontrar um iterador primeiro:
>>> X = [1,2,3,4,5]
>>> bricks_kit = [1,2,3,4,5]
>>> white_piece_of_paper = iter(bricks_kit)
>>> next(white_piece_of_paper)
1
>>> next(white_piece_of_paper)
2
>>>
Não sei se ajuda, mas me ajudou. Se alguém pudesse confirmar / corrigir a visualização do conceito, ficaria agradecido. Isso me ajudaria a aprender mais.
Iterável : - algo que é iterável é iterável; como seqüências como listas, strings, etc. Também possui o __getitem__método ou um __iter__método. Agora, se usarmos a iter()função nesse objeto, obteremos um iterador.
Iterador : - Quando obtemos o objeto iterador da iter()função; chamamos __next__()método (em python3) ou simplesmente next()(em python2) para obter os elementos um a um. Essa classe ou instância dessa classe é chamada de iterador.
Dos documentos: -
O uso de iteradores permeia e unifica o Python. Nos bastidores, a instrução for chama iter() o objeto contêiner. A função retorna um objeto iterador que define o método __next__() que acessa elementos no contêiner, um de cada vez. Quando não há mais elementos, __next__() gera uma exceção StopIteration que informa ao loop for para terminar. Você pode chamar o __next__() método usando a next() função interna; este exemplo mostra como tudo funciona:
>>> s = 'abc'
>>> it = iter(s)
>>> it
<iterator object at 0x00A1DB50>
>>> next(it)
'a'
>>> next(it)
'b'
>>> next(it)
'c'
>>> next(it)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
next(it)
StopIteration
Ex de uma classe: -
class Reverse:
"""Iterator for looping over a sequence backwards."""
def __init__(self, data):
self.data = data
self.index = len(data)
def __iter__(self):
return self
def __next__(self):
if self.index == 0:
raise StopIteration
self.index = self.index - 1
return self.data[self.index]
>>> rev = Reverse('spam')
>>> iter(rev)
<__main__.Reverse object at 0x00A1DB50>
>>> for char in rev:
... print(char)
...
m
a
p
s
Eu não acho que você pode simplificar muito mais que a documentação , no entanto, tentarei:
Você pode pensar no Iterator como um pseudo-método auxiliar (ou pseudo-atributo) que fornece (ou retém) o próximo (ou primeiro) item no iterável . (Na prática, é apenas um objeto que define o método next())
A iteração é provavelmente melhor explicada pela definição Merriam-Webster da palavra :
b: a repetição de uma sequência de instruções do computador um número especificado de vezes ou até que uma condição seja atendida - compare a recursão
iterable = [1, 2]
iterator = iter(iterable)
print(iterator.__next__())
print(iterator.__next__())
tão,
iterableé um objeto que pode ser repetido . por exemplo, lista, string, tupla etc.
usar a iterfunção em nosso iterableobjeto retornará um objeto iterador.
agora esse objeto iterador possui um método chamado __next__(no Python 3 ou apenas nextno Python 2) pelo qual você pode acessar cada elemento do iterável.
portanto, a SAÍDA DO CÓDIGO ACIMA SERÁ:
1
2
Os iteráveis têm um
__iter__método que instancia um novo iterador sempre.Os iteradores implementam um
__next__método que retorna itens individuais e um__iter__método que retornaself.Portanto, os iteradores também são iteráveis, mas iterables não são iteradores.
Luciano Ramalho, Python Fluente.
Antes de lidar com os iteráveis e o iterador, o principal fator que decide o iterável e o iterador é a sequência
Sequência: Sequência é a coleta de dados
Iterável: Iterável é o objeto do tipo sequência que suporta o __iter__método.
Método Iter: o método Iter toma a sequência como uma entrada e cria um objeto que é conhecido como iterador
Iterador: Iterador é o objeto que chama o próximo método e transversal através da sequência. Ao chamar o próximo método, ele retorna o objeto que ele atravessou atualmente.
exemplo:
x=[1,2,3,4]
x é uma sequência que consiste na coleta de dados
y=iter(x)
Ao chamar, iter(x)ele retorna um iterador apenas quando o objeto x tem o método iter, caso contrário, gera uma exceção.Se ele retorna o iterador, y é atribuído assim:
y=[1,2,3,4]
Como y é um iterador, portanto, ele suporta next() método
Ao chamar o próximo método, ele retorna os elementos individuais da lista, um por um.
Depois de retornar o último elemento da sequência, se chamarmos novamente o próximo método, gera um erro StopIteration
exemplo:
>>> y.next()
1
>>> y.next()
2
>>> y.next()
3
>>> y.next()
4
>>> y.next()
StopIteration
No Python, tudo é um objeto. Quando se diz que um objeto é iterável, significa que você pode percorrer (ou seja, iterar) o objeto como uma coleção.
Matrizes, por exemplo, são iteráveis. Você pode percorrê-los com um loop for e passar do índice 0 ao índice n, sendo n o comprimento do objeto da matriz menos 1.
Dicionários (pares de chave / valor, também chamados de matrizes associativas) também são iteráveis. Você pode percorrer as chaves deles.
Obviamente, os objetos que não são coleções não são iteráveis. Um objeto bool, por exemplo, tem apenas um valor, Verdadeiro ou Falso. Não é iterável (não faria sentido que seja um objeto iterável).
Consulte Mais informação. http://www.lepus.org.uk/ref/companion/Iterator.xml
iter()os tipos de coleção padrão são iteráveis, mas não são coleções em si.
collections.abc.AsyncIteratortestes para__aiter__e__anext__métodos. Esta é uma nova adição no 3.6.