Pourquoi ne définissant __getitem__ sur une classe en faire itérable en python?
Pourquoi ne définissant __getitem__ sur une classe en faire itératif?
Par exemple, si j'écris:
class b:
def __getitem__(self, k):
return k
cb = b()
for k in cb:
print k
- Je obtenir la sortie:
0
1
2
3
4
5
6
7
8
...
Je voudrais vraiment s'attendre à voir une erreur retourné à partir de "pour k cb:"
Vous devez vous connecter pour publier un commentaire.
Si vous jetez un oeil à PEP234 la définition des itérateurs, il dit:
Itération de soutien pour
__getitem__
peut être vu comme un "héritage de la fonctionnalité" qui a permis de transition plus en douceur lorsque PEP234 introduit iterability comme un concept primaire. Elle ne s'applique qu'à des classes sans__iter__
dont__getitem__
accepte les entiers 0, 1, &c, et soulèveIndexError
une fois l'indice est trop élevée (si jamais), généralement sur la "séquence" classes codées avant__iter__
est apparu (mais rien ne vous empêche de codage de nouvelles classes de cette façon).Personnellement, je préfère ne pas compter sur ce nouveau code, si ce n'est pas obsolète, ni est-il en aller (fonctionne très bien en Python 3 trop), donc c'est juste une question de style et de goût ("explicite est mieux qu'implicite" donc, je préfère explicitement iterability plutôt que de compter sur
__getitem__
soutenir implicitement pour moi -- mais, pas un bigge).__getitem__
a été introduit pour créer iterables, il a été fait avec[]
attribut de l'accès à l'esprit? En lisant les réponses, il me semble que si vous voulez[]
attribut d'accès et un objet iterable vous ne pouvez pas faire cela en utilisant seulement__getitem__
. Vous devez ensuite utiliser__getitem__
pour[]
accès et__iter__
pour l'itérateur, correct?__getitem__
est que tout type entier va avoir une limite supérieure, de sorte que l'accès indexé pourrait heurter des que. Alors que__next__
pouvez continuer gaiement à l'infini. (Au moins, c'est ma compréhension.)__getitem__
est antérieure à l'itérateur protocole, et a été dans le passé le seulement façon de faire les choses itératif. En tant que tel, il est toujours pris en charge en tant que méthode d'itération. Essentiellement, le protocole pour l'itération est:Vérifier la présence d'une
__iter__
méthode. Si elle existe, l'utilisation de la nouvelle itération de protocole.Sinon, essayez d'appeler
__getitem__
avec successivement les grandes valeurs entières jusqu'à ce qu'il soulève IndexError.(2) utilisé pour être le seul moyen de le faire, mais a l'inconvénient que cela suppose de plus que ce qui était nécessaire pour le support de l'itération. À l'appui de l'itération, vous avez eu à l'appui de l'accès aléatoire, qui était beaucoup plus cher pour des choses comme des fichiers ou des flux de réseau où aller en avant a été facile, mais à reculons aurait besoin de stocker tout.
__iter__
permis itération sans accès aléatoire, mais depuis l'accès aléatoire permet généralement d'itération de toute façon, et parce que la rupture de compatibilité descendante serait mauvais,__getitem__
est toujours pris en charge.Méthodes spéciales telles que
__getitem__
ajouter des comportements à des objets, y compris itération.http://docs.python.org/reference/datamodel.html#object.getitem
"pour les boucles s'attendre à ce que un IndexError seront soulevées illicite des indices afin de permettre une bonne détection de la fin de la séquence."
Élever IndexError pour signaler la fin de la séquence.
Votre code est essentiellement équivalent à:
Où l'objet est ce que vous avez à parcourir dans la boucle for.
Il en est ainsi pour des raisons historiques. Avant de Python 2.2 __getitem__ était la seule façon de créer une classe qui pourrait être itéré avec la boucle for. 2.2 l' __iter__ protocole a été ajouté, mais pour conserver la compatibilité descendante __getitem__ travaille toujours dans des boucles for.
Parce que
cb[0]
est le même quecb.__getitem__(0)
. Voir la la documentation python sur ce.