Why does defining __getitem__ on a class make it iterable in python?

class object is not iterable python
python __getitem__
python __iter__
django __getitem__
python implement __getitem__
python iterator
python class iterator
iterator protocol python

Why does defining __getitem__ on a class make it iterable?

For instance if I write:

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

cb = b()

for k in cb:
  print k

I get the output:

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

I would really expect to see an error returned from "for k in cb:"

If you take a look at PEP234 defining iterators, it says:

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

Making an iterable class: should I just implement __getitem__ and , Is getitem and len being special for making iterable objects going away? Making an iterable class: should I just implement __getitem__ and __len__, or __ iter__ returning As far as I can tell, it basically just forces you to define __iter__ . "Automate the Boring Stuff with Python" online course is free to sign up for the next� __getitem__ predates the iterator protocol, and was in the past the only way to make things iterable. As such, it’s still supported as a method of iterating. Essentially, the protocol for iteration is:

Iteration's support for __getitem__ can be seen as a "legacy feature" which allowed smoother transition when PEP234 introduced iterability as a primary concept. It only applies to classes without __iter__ whose __getitem__ accepts integers 0, 1, &c, and raises IndexError once the index gets too high (if ever), typically "sequence" classes coded before __iter__ appeared (though nothing stops you from coding new classes this way too).

Personally, I would rather not rely on this in new code, though it's not deprecated nor is it going away (works fine in Python 3 too), so this is just a matter of style and taste ("explicit is better than implicit" so I'd rather explicitly support iterability rather than rely on __getitem__ supporting it implicitly for me -- but, not a bigge).

3 practical Python tools: magic methods, iterators and generators , Tools to make your Python code more elegant, readable, intuitive, and A common magic method you may be familiar with is __init__() The class defines a currency rate for a given symbol and exchange For example, to access an item by index or key (in the case of a dictionary), use the __getitem__� Why does defining__getitem__ on a class make it iterable in python? (4) __getitem__ predates the iterator protocol, and was in the past the only way to make things iterable. As such, it's still supported as a method of iterating.

__getitem__ predates the iterator protocol, and was in the past the only way to make things iterable. As such, it's still supported as a method of iterating. Essentially, the protocol for iteration is:

  1. Check for an __iter__ method. If it exists, use the new iteration protocol.

  2. Otherwise, try calling __getitem__ with successively larger integer values until it raises IndexError.

(2) used to be the only way of doing this, but had the disadvantage that it assumed more than was needed to support just iteration. To support iteration, you had to support random access, which was much more expensive for things like files or network streams where going forwards was easy, but going backwards would require storing everything. __iter__ allowed iteration without random access, but since random access usually allows iteration anyway, and because breaking backward compatability would be bad, __getitem__ is still supported.

Python's Old Iteration Protocol, What is Python's old-style iteration protocol? Does it have anything to do with the difference between old-style and new-style classes? Making an object Iterable just means defining the __iter__ method to class MySequence: def __getitem__(self, i): if i > 3: raise IndexError() return str(i) . I want to define a class that supports __getitem__, but does not allow iteration. for example: class B: def __getitem__(self, k): return k cb = B() for x in cb: print x What could I add to the class B to force the for x in cb: to fail?

Special methods such as __getitem__ add special behaviors to objects, including iteration.

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

"for loops expect that an IndexError will be raised for illegal indexes to allow proper detection of the end of the sequence."

Raise IndexError to signal the end of the sequence.

Your code is basically equivalent to:

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

Where object is what you're iterating over in the for loop.

3. Generators — Python Tips 0.1 documentation, Classes � 18. Lambdas � 19. 3.1. Iterable�. An iterable is any object in Python which has an __iter__ or a __getitem__ method defined which returns an iterator or can take indexes (You can read more about them here). It's because they do not store all the values in memory, they generate the values on the fly. You use� 5. Any object with an __iter__ () method is considered an iterable. Additionally, any sequence (objects that have an __getitem__ () method) could return an iterator. An iterator is an object with a __next__ () method that returns the next object in the sequence and throws a StopIteration exception. share.

This is so for historical reasons. Prior to Python 2.2 __getitem__ was the only way to create a class that could be iterated over with the for loop. In 2.2 the __iter__ protocol was added but to retain backwards compatibility __getitem__ still works in for loops.

collections.abc — Abstract Base Classes for Containers — Python , This module provides abstract base classes that can be used to test whether a class provides a __call__. Collection. Sized , Iterable , Container. __contains __ , __iter__ , __len__ __getitem__ , __setitem__ , __delitem__ , __len__ , insert ABC for generator classes that implement the protocol defined in PEP 342 that� Iterator in Python is simply an object that can be iterated upon. An object which will return data, one element at a time. Technically speaking, a Python iterator object must implement two special methods, __iter__() and __next__(), collectively called the iterator protocol. An object is called iterable if we can get an

3. Data model — Python 2.7.18 documentation, The name of the module the function was defined in, or None if unavailable. Such a function, when called, always returns an iterator object which can be used to __getitem__(i) for old-style classes and type(x). Typical implementations create a new instance of the class by invoking the superclass's __new__() method� That is why any Python sequence is iterable: they all implement __getitem__. In fact, the standard sequences also implement __iter__ , and yours should too, because the special handling of __getitem__ exists for backward compatibility reasons and may be gone in the future (although it is not deprecated as I write this).

3. Data model — Python 3.8.5 documentation, Such a function, when called, always returns an iterator object which can be used to execute the body of the function: Instances of arbitrary classes can be made callable by defining a __call__() method in their class. __getitem__(x, i) . This is Python’s approach to operator overloading, allowing classes to define their own behavior with respect to language operators. For instance, if a class defines a method named __getitem__(), and x is an instance of this class, then x[i] is roughly equivalent to type(x).__getitem__(x, i).

Python iterable and iterator a tutorial, In python , objects are abstraction of data , they have methods "__class__",. "__ contains__", "__getitem__", An iterable object is an object that defines a way to Iterate simply means to loop over each of its elements , and do something with , like printing or calculating the�

Comments
  • The usefulness of this reply is akin to if a child asked why the sky is blue and you responded "because God made it so." Here, have some of my vitriol.
  • When __getitem__ was introduced to create iterables, was it done with [] attribute access in mind? From reading the answers, it seems to me that if you want [] attribute access and an iterable you cannot do this using only __getitem__. You should then use __getitem__ for [] access and __iter__ for the iterator, correct?
  • Another point against __getitem__ is that any integer type is going to have an upper limit, so indexed access could bump into that. Whereas __next__ can keep going happily ad infinitum. (At least, that's my understanding.)
  • Just noting that pythons int has no limit. It is an arbitrary size integer.
  • yes, thank you, this answered "if it ain't broken why fix it?" question I had.
  • True, but __getitem__() is not the same as __iter__().