27 votes

Pourquoi le fait de définir __getitem__ sur une classe la rend itérable en python ?

Pourquoi le fait de définir __getitem__ sur une classe la rend itérable ?

Par exemple, si j'écris :

class b:
  def __getitem__(self, k):
    return k

cb = b()

for k in cb:
  print k

J'obtiens le résultat :

0
1
2
3
4
5
6
7
8
...

Je m'attendrais vraiment à voir une erreur renvoyée par "for k in cb :"

40voto

Alex Martelli Points 330805

Le support de l'itération pour __getitem__ peut être considéré comme une "fonctionnalité héritée" qui a permis une transition plus douce lorsque PEP234 a introduit l'itérabilité comme concept primaire. Elle ne s'applique qu'aux classes sans __iter__ dont __getitem__ accepte les entiers 0, 1, &c, et soulève IndexError une fois que l'indice devient trop élevé (si jamais), typiquement les classes de "séquence" codées avant __iter__ est apparu (bien que rien ne vous empêche de coder de nouvelles classes de cette manière également).

Personnellement, je préférerais ne pas m'appuyer sur cette fonction dans un nouveau code, bien qu'elle ne soit pas dépréciée et qu'elle ne disparaisse pas non plus (elle fonctionne bien dans Python 3 également), c'est donc juste une question de style et de goût ("l'explicite est meilleur que l'implicite", donc je préférerais supporter explicitement l'itérabilité plutôt que de m'appuyer sur __getitem__ le soutenant implicitement pour moi - mais, pas un bigge).

28voto

scompt.com Points 11304

Si vous jetez un coup d'œil à PEP234 en définissant les itérateurs, il est dit :

1. An object can be iterated over with "for" if it implements
   __iter__() or __getitem__().

2. An object can function as an iterator if it implements next().

15voto

Brian Points 48423

__getitem__ est antérieur au protocole des itérateurs, et était dans le passé le uniquement manière de rendre les choses itérables. En tant que tel, il est toujours supporté comme une méthode d'itération. Essentiellement, le protocole d'itération est le suivant :

  1. Vérifiez si un __iter__ méthode. S'il existe, utilisez le nouveau protocole d'itération.

  2. Sinon, essayez d'appeler __getitem__ avec des valeurs entières de plus en plus grandes jusqu'à ce qu'il déclenche IndexError.

(2) était la seule façon de le faire, mais elle avait l'inconvénient de supposer plus que ce qui était nécessaire pour supporter l'itération. Pour supporter l'itération, vous deviez supporter l'accès aléatoire, ce qui était beaucoup plus coûteux pour des choses comme les fichiers ou les flux réseau où avancer était facile, mais revenir en arrière nécessitait de tout stocker. __iter__ permettait l'itération sans accès aléatoire, mais puisque l'accès aléatoire permet généralement l'itération de toute façon, et parce que briser la compatibilité en arrière serait mauvais, __getitem__ est toujours supporté.

4voto

FogleBird Points 23405

Des méthodes spéciales telles que __getitem__ ajouter des comportements spéciaux aux objets, notamment l'itération.

http://docs.python.org/reference/datamodel.html#object. getitem

"Les boucles for prévoient qu'une IndexError sera levée pour les index illégaux afin de permettre une détection correcte de la fin de la séquence."

Soulevez IndexError pour signaler la fin de la séquence.

Votre code est fondamentalement équivalent à :

i = 0
while True:
    try:
        yield object[i]
        i += 1
    except IndexError:
        break

Où l'objet est ce sur quoi vous itérez dans la boucle for.

4voto

Ants Aasma Points 22921

Il en est ainsi pour des raisons historiques. Avant Python 2.2, __getitem__ était le seul moyen de créer une classe qui pouvait être itérée avec la boucle for. Dans la version 2.2, le protocole __iter__ a été ajouté, mais pour conserver la compatibilité ascendante, __getitem__ fonctionne toujours dans les boucles for.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X