Let's say I have a class which implements an __iter__()
function, is it preferred to use iter(obj)
or calling obj.__iter__()
directly? Are there any real differences besides having to type 5 characters less with the magic function?
In contrast: For next()
and __next__()
I can see an advantage for having a default value with the magic function.
The difference is mostly just convenience. It's less typing and less symbols to read, and so faster to read. However, the various builtin functions (eg. iter
, len
et al.) usually do a little type checking to catch errors early. If you wrote a customer __iter__
method and it returned 2
, then invoking obj.__iter__()
wouldn't catch that, but iter(obj)
throws a type error. eg.
>>> class X:
def __iter__(self):
return 2
>>> x = X()
>>> x.__iter__()
2
>>> iter(x)
Traceback (most recent call last):
File "<pyshell#37>", line 1, in <module>
iter(x)
TypeError: iter() returned non-iterator of type 'int'
iter
also implements the iterator protocol for objects that have no __iter__
, but do implement the sequence protocol. That is, they have a __getitem__
method which implements a sequence starting at index 0 and raises an IndexError for indexes not in bounds. This is an older feature of python and not really something new code should be using. eg.
>>> class Y:
def __getitem__(self, index):
if 0 <= index < 5:
return index ** 2
else:
raise IndexError(index)
>>> list(iter(Y())) # iter not strictly needed here
[0, 1, 4, 9, 16]
When should you use __iter__
? This might not be so relevant to __iter__
, but if you need access to the implementation of method that the parent class uses then it is best to invoke such methods in the style super().__<dunder_method>__()
(using Python 3 style super usage). eg.
>>> class BizzareList(list):
def __iter__(self):
for item in super().__iter__():
yield item * 10
>>> l = BizzareList(range(5))
>>> l # normal access
[0, 1, 2, 3, 4]
>>> l[0] # also normal access
0
>>> tuple(iter(l)) # iter not strictly needed here
(0, 10, 20, 30, 40)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With