2009-05-29 11 views

Respuesta

39

Si se echa un vistazo a PEP234 iteradores que definen, que dice: el apoyo

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(). 
3

Porque cb[0] es lo mismo que cb.__getitem__(0). Vea el python documentation en esto.

+1

Cierto, pero __getitem __() no es lo mismo que __iter __(). – grieve

5

Los métodos especiales como __getitem__ añaden comportamientos especiales a los objetos, incluida la iteración.

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

"para los bucles esperar que un IndexError será elevado para los índices ilegales para permitir la detección apropiada de la final de la secuencia."

Levante IndexError para señalar el final de la secuencia.

Su código es básicamente equivalente a:

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

Donde objeto es lo que está en la iteración en el bucle.

47

de iteración para __getitem__ puede ser visto como una "característica legado" que permitió la transición más suave cuando PEP234 introdujo iterabilidad como concepto primario. Solo se aplica a las clases sin __iter__ cuyo __getitem__ acepta números enteros 0, 1, & c, y aumenta IndexError una vez que el índice es demasiado alto (si alguna vez), por lo general aparecen "secuencias" codificadas antes de __iter__ (aunque nada impide codificar nuevas clases de esta manera también).

Personalmente, prefiero no confiar en esto en un código nuevo, aunque no está en desuso ni se va a ir (funciona bien en Python 3 también), así que esto es solo cuestión de estilo y gusto ("explicito es mejor") que implícita "así que preferiría apoyar explícitamente la iterabilidad en lugar de confiar en __getitem__ para que la respalde implícitamente para mí, pero no como un bigge).

+0

Cuando '__getitem__' se introdujo para crear iterables, ¿se hizo con el acceso a atributos' [] 'en mente? Al leer las respuestas, me parece que si quieres el acceso a atributos '[]' _y _ una iterable, no puedes hacer esto usando solo '__getitem__'. Deberías usar '__getitem__' para' [] 'access y' __iter__' para el iterador, ¿correcto? – lmichelbacher

+0

@lmichelbacher: por supuesto que puedes, mira la respuesta por FogleBird – kriss

+0

Otro punto en contra de '__getitem__' es que cualquier tipo entero va a tener un límite superior, por lo que el acceso indexado podría toparse con eso. Mientras que '__next__' puede continuar felizmente ad infinitum. (Al menos, eso es lo que entiendo.) –

19

__getitem__ anterior del protocolo de iteración, y fue en el pasado la única manerapara hacer las cosas iterable. Como tal, todavía es compatible como un método de iteración. Esencialmente, el protocolo para la iteración es:

  1. Compruebe si hay un método __iter__. Si existe, use el nuevo protocolo de iteración.

  2. De lo contrario, intente llamar al __getitem__ con valores enteros sucesivamente más grandes hasta que aparezca IndexError.

(2) que solía ser la única manera de hacer esto, pero tenía el inconveniente de que supone más de lo necesario para apoyar simplemente iteración. Para admitir la iteración, tenía que admitir el acceso aleatorio, que era mucho más costoso para cosas como archivos o secuencias de red, donde ir hacia adelante era fácil, pero retroceder exigiría almacenar todo. __iter__ permitió la iteración sin acceso aleatorio, pero dado que el acceso aleatorio generalmente permite la iteración de todos modos, y porque la compatibilidad con versiones anteriores sería malo, __getitem__ sigue siendo compatible.

+0

¡Buen punto en el acceso aleatorio! – crennie

+0

sí, gracias, esto respondió "si no está roto, ¿por qué arreglarlo?" pregunta que tuve. – m1keil

5

Esto es así por razones históricas. Antes de Python 2.2 __getitem__ era la única forma de crear una clase que pudiera repetirse con el ciclo for. En 2.2 se agregó el protocolo __iter__ pero para mantener la compatibilidad con versiones anteriores __getitem__ aún funciona en bucles.

Cuestiones relacionadas