Quelle est la définition la plus élémentaire de "iterable", "iterator" et "iteration" en Python?
J'ai lu plusieurs définitions mais je ne parviens pas à identifier le sens exact car il ne sera toujours pas intégré.
Quelqu'un peut-il m'aider s'il vous plaît avec les 3 définitions en termes simples?
Itération est un terme général désignant chaque élément de quelque chose, l'un après l'autre. Chaque fois que vous utilisez une boucle, explicite ou implicite, pour parcourir un groupe d’éléments, c’est une itération.
En Python, iterable et iterator ont une signification spécifique.
Un iterable est un objet qui a une méthode __iter__
qui retourne un iterator , ou qui définit un __getitem__
méthode qui peut prendre des index séquentiels à partir de zéro (et déclenche un IndexError
lorsque les index ne sont plus valides). Donc un iterable est un objet dont vous pouvez obtenir un iterator .
Un iterator est un objet avec une méthode next
(Python 2) ou __next__
(Python 3).
Chaque fois que vous utilisez une boucle for
, ou map
, ou une compréhension de liste, etc. en Python, la méthode next
est automatiquement appelée pour obtenir chaque élément de itérateur , passant ainsi par le processus de itération .
Un bon endroit pour commencer à apprendre serait le section des itérateurs du tutoriel et le section des types d'itérateurs de la page des types standard . Une fois que vous avez compris les bases, essayez la section itérateurs du HOWTO Programmation fonctionnelle .
Voici l'explication que j'utilise dans l'enseignement de Python classes:
Un ITERABLE est:
for x in iterable: ...
ouiter()
qui retournera un ITERATOR: iter(obj)
ou__iter__
qui retourne un ITERATOR neuf, ou une méthode __getitem__
appropriée pour la recherche indexée.Un ITERATOR est un objet:
__next__
qui: StopIteration
__iter__
qui retourne self
).Remarques:
__next__
dans Python 3 est orthographiée next
dans Python 2, etnext()
appelle cette méthode sur l'objet qui lui est transmis.Par exemple:
>>> 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
Les réponses ci-dessus sont excellentes, mais comme la plupart de ce que j'ai vu, n'insistez pas assez sur la distinction pour des personnes comme moi.
De plus, les gens ont tendance à se faire "trop Pythonic" en mettant des définitions comme "X est un objet qui a la méthode __foo__()
avant". Ces définitions sont correctes - elles sont basées sur la philosophie de la typographie, mais l'accent mis sur les méthodes a tendance à se situer entre les efforts lorsque l'on tente de comprendre le concept dans sa simplicité.
Alors j'ajoute ma version.
En langage naturel,
En python,
iterable est un objet qui est, ainsi, iterable, ce qui signifie simplement qu'il peut être utilisé dans une itération, par exemple. avec une boucle for
. Comment? En utilisant itérateur . Je vais expliquer ci-dessous.
... while itérateur est un objet qui définit comment effectuer l'itération - spécifiquement quel est le prochain élément. C'est pourquoi il doit avoir la méthode next()
.
Les itérateurs sont eux aussi itératifs, à la différence que leur méthode __iter__()
renvoie le même objet (self
), que ses éléments aient été consommés ou non lors d'appels précédents à next()
.
Alors, que pense l’interprète Python quand il voit la déclaration for x in obj:
?
Regardez, une boucle
for
. On dirait un travail pour un itérateur ... Allons en avoir un. ... Il y a ce garsobj
alors demandons-lui."M.
obj
, avez-vous votre itérateur?" (... appelleiter(obj)
, qui appelleobj.__iter__()
, qui distribue avec bonheur un nouvel itérateur brillant_i
.)OK, c'était facile ... Commençons donc par itérer. (
x = _i.next()
...x = _i.next()
...)
Puisque M. obj
a réussi ce test (en renvoyant une certaine méthode à un itérateur valide), nous le récompensons avec un adjectif: vous pouvez maintenant l'appeler "M. itérable _ obj
".
Cependant, dans les cas simples, il n'est normalement pas avantageux d'avoir itérateur et itérable séparément. Vous définissez donc un seul objet , qui est également son propre itérateur. (Python ne s'inquiète pas vraiment que _i
distribué par obj
n'était pas si brillant, mais juste le obj
lui-même.)
C'est pourquoi, dans la plupart des exemples que j'ai vus (et ce qui m'avait dérouté encore et encore), vous pouvez voir:
class IterableExample(object):
def __iter__(self):
return self
def next(self):
pass
au lieu de
class Iterator(object):
def next(self):
pass
class Iterable(object):
def __iter__(self):
return Iterator()
Il existe cependant des cas dans lesquels vous pouvez tirer avantage de la séparation de l'itérateur de l'itérable, par exemple lorsque vous souhaitez avoir une ligne d'éléments, mais davantage de "curseurs". Par exemple, lorsque vous souhaitez utiliser les éléments "en cours" et "à venir", vous pouvez avoir des itérateurs séparés pour les deux. Ou plusieurs threads tirés d'une liste énorme: chacun peut avoir son propre itérateur à parcourir sur tous les éléments. Voir les réponses @ Raymond's et @ glglgl's ci-dessus.
Imaginez ce que vous pourriez faire:
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()
Remarques:
Je répète: l'itérateur n'est pas itérable . L'itérateur ne peut pas être utilisé comme "source" dans la boucle for
. La boucle for
dont nous avons principalement besoin est __iter__()
(qui renvoie quelque chose avec next()
).
Bien entendu, for
n’est pas la seule boucle d’itération, ce qui précède s’applique également à certaines autres constructions (while
...).
La fonction next()
d'Iterator peut lancer StopIteration pour arrêter l'itération. N'a pas à le faire, cependant, il peut itérer pour toujours ou utiliser d'autres moyens.
Dans le "processus de pensée" ci-dessus, _i
n'existe pas vraiment. J'ai inventé ce nom.
Il y a un petit changement dans la méthode Python 3.x: _ La méthode next()
(et non la fonction intégrée) doit maintenant s'appeler __next__()
. Oui, ça aurait dû être comme ça depuis le début.
Vous pouvez aussi penser à ça comme ceci: iterable a les données, iterator tire le prochain article
Avertissement: Je ne suis développeur d'aucun interpréteur Python, je ne sais donc pas vraiment ce que l'interprète "pense". Les réflexions ci-dessus démontrent uniquement comment je comprends le sujet à partir d'autres explications, expériences et expériences réelles d'un débutant Python.
Un iterable est un objet qui a une méthode __iter__()
. Il peut éventuellement être itéré plusieurs fois, tels que list()
s et Tuple()
s.
Un itérateur est l'objet qui itère. Elle est renvoyée par une méthode __iter__()
, se renvoie elle-même via sa propre méthode __iter__()
et possède une méthode next()
(__next__()
dans 3.x).
L'itération est le processus d'appel de cette next()
resp. __next__()
jusqu'à ce qu'il augmente StopIteration
.
Exemple:
>>> 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
Je ne sais pas si cela aide quelqu'un, mais j'aime toujours visualiser des concepts dans ma tête pour mieux les comprendre. Donc, comme j'ai un petit fils, je visualise un concept itérable/itérateur avec des briques et du papier blanc.
Supposons que nous sommes dans la pièce sombre et sur le sol que nous avons des briques pour mon fils. Des briques de différentes tailles, couleurs, n’a plus d’importance. Supposons que nous ayons 5 briques comme celles-ci. Ces 5 briques peuvent être décrites comme un objet - disons kit de briques . Nous pouvons faire beaucoup de choses avec ce kit de briques - nous pouvons en prendre une, puis prendre la deuxième et la troisième, puis changer de place de briques, placer la première brique au-dessus de la seconde. Nous pouvons faire beaucoup de choses avec cela. Par conséquent, ce kit de briques est un objet itérable ou séquence car nous pouvons passer en revue chaque brique et en faire quelque chose. Nous ne pouvons le faire que comme mon petit fils - nous pouvons jouer avec ne brique à la fois. Alors encore une fois, je m'imagine que ce kit de briques est un iterable.
Maintenant rappelez-vous que nous sommes dans la pièce sombre. Ou presque sombre. Le fait est que nous ne voyons pas clairement ces briques, leur couleur, leur forme, etc. Donc, même si nous voulons faire quelque chose avec elles - aka parcourir par elles - nous ne le faisons pas vraiment savoir quoi et comment car il fait trop sombre.
Ce que nous pouvons faire, c'est près de la première brique - en tant qu'élément d'un kit de briques - nous pouvons mettre un morceau de papier fluorescent blanc afin de nous permettre de voir où se trouve le premier élément de brique. Et chaque fois que nous prenons une brique d'un kit, nous remplaçons le morceau de papier blanc par une brique suivante afin de pouvoir le voir dans la pièce sombre. Ce morceau de papier blanc n’est rien de plus qu’un itérateur. C'est un objet aussi. Mais un objet avec lequel nous pouvons travailler et jouer avec des éléments de notre kit éditable d’objets - briques.
Cela explique d'ailleurs ma première erreur lorsque j'ai essayé ce qui suit dans un IDLE et obtenu un 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
La liste X ici était notre kit de briques mais PAS un morceau de papier blanc. Je devais d'abord trouver un itérateur:
>>> 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
>>>
Je ne sais pas si ça aide, mais ça m’a aidé. Si quelqu'un pouvait confirmer/corriger la visualisation du concept, je vous en serais reconnaissant. Cela m'aiderait à en apprendre plus.
Voici mon aide-mémoire:
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: Voyez-vous comment ...
__iter__()
d'un objet conteneur peut être implémentée en tant que générateur?__next__
n'est pas nécessairement un itérateur?Iterable: - quelque chose qui est iterable est iterable; comme des séquences telles que des listes, des chaînes, etc. De plus, il possède soit la méthode __getitem__
, soit une méthode __iter__
. Maintenant, si nous utilisons la fonction iter()
sur cet objet, nous aurons un itérateur.
Itérateur: - Lorsque nous obtenons l'objet itérateur de la fonction iter()
; nous appelons la méthode __next__()
(en python3) ou simplement next()
(en python2) pour obtenir les éléments un à un. Cette classe ou instance de cette classe s'appelle un itérateur.
De la documentation: -
L'utilisation d'itérateurs imprègne et unifie Python. En coulisse, l'instruction for appelle iter()
sur l'objet conteneur. La fonction renvoie un objet itérateur définissant la méthode __next__()
, qui accède aux éléments du conteneur, un à la fois. Lorsqu'il n'y a plus d'éléments, __next__()
génère une exception StopIteration qui indique à la boucle for de se terminer. Vous pouvez appeler la méthode __next__()
à l'aide de la fonction intégrée next()
; Cet exemple montre comment tout cela fonctionne:
>>> 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 d'un cours: -
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
Je ne pense pas que vous puissiez l’obtenir beaucoup plus simplement que documentation , mais je vais essayer:
Vous pouvez penser Iterator en tant que pseudo-méthode d'assistance (ou pseudo-attribut) qui donne (ou maintient) l'élément suivant (ou le premier) dans l'élément iterable . (En pratique, c'est juste un objet qui définit la méthode next()
)
L'itération est probablement mieux expliquée par le Merriam-Webster définition du mot :
b: répétition d'une séquence d'instructions de l'ordinateur un nombre spécifié de fois ou jusqu'à ce qu'une condition soit remplie - comparer la récursivité
iterable = [1, 2]
iterator = iter(iterable)
print(iterator.__next__())
print(iterator.__next__())
alors,
iterable
est un objet pouvant être survolé. par exemple. liste, chaîne, tuple, etc.
utiliser la fonction iter
sur notre objet iterable
renverra un objet itérateur.
maintenant cet objet itérateur a une méthode nommée __next__
(dans Python 3, ou tout simplement next
dans Python 2) par laquelle peut accéder à chaque élément de iterable.
alors, SORTIE DE CODE CI-DESSUS SERA:
1
2
Iterables possède une méthode
__iter__
qui instancie un nouvel itérateur à chaque fois.Itérateurs implémente une méthode
__next__
qui renvoie des éléments individuels et une méthode__iter__
qui renvoieself
.Par conséquent, les itérateurs sont également itérables, mais les itérables ne sont pas des itérateurs.
Luciano Ramalho, Python Courant.
Avant de traiter avec les itérables et les itérateurs, le facteur principal qui détermine l’itérateur et les itérateurs est la séquence.
Séquence: La séquence est la collecte de données
Iterable: Iterable est l'objet de type séquence qui prend en charge la méthode Iter.
Méthode Iter: la méthode Iter prend une séquence en tant qu'entrée et crée un objet appelé itérateur
Itérateur: Les itérateurs sont les objets qui appellent la méthode suivante et transversalement à travers la séquence. Lors de l'appel de la méthode suivante, l'objet retourné est renvoyé.
exemple:
x=[1,2,3,4]
x est une séquence qui consiste en une collecte de données
y=iter(x)
En appelant iter (x), il retourne un itérateur uniquement lorsque l'objet x a une méthode iter, sinon une exception est déclenchée. S'il renvoie itérateur, y est assigné comme ceci:
y=[1,2,3,4]
Comme y est un itérateur, il prend en charge la méthode next ()
Lors de l'appel de la méthode suivante, les éléments individuels de la liste sont renvoyés un par un.
Après avoir renvoyé le dernier élément de la séquence, si nous appelons à nouveau la méthode suivante, une erreur StopIteration est renvoyée.
exemple:
>>> y.next()
1
>>> y.next()
2
>>> y.next()
3
>>> y.next()
4
>>> y.next()
StopIteration