*Memos:
- My post explains an iterator (1).
- My post explains an iterator (2) and copy.
- My post explains a generator.
You can create a class-based iterator with __iter__() and/or __next__() as shown below:
*Memos:
- Basically,
__iter__()
is used to return an iterator. - Basically,
__next__()
is used to return the next element.
<iter() & next()>
class Cls:
data = ['a', 'b', 'c']
index = 0
def __iter__(self):
return self
def __next__(self):
if self.index < len(self.data):
i = self.index
self.index += 1
return self.data[i]
raise StopIteration
v = Cls()
print(v) # <__main__.Cls object at 0x000001FCD688B350>
# It gets an element but it's not necessary for
# a `for` statement, `__next__()` and `next()`.
v = v.__iter__()
print(v) # <__main__.Cls object at 0x000001FCD688B350>
# It gets an element but it's not necessary for
# a `for` statement, `__next__()` and `next()`.
v = iter(v)
print(v) # <__main__.Cls object at 0x000001FCD688B350>
for x in v:
print(x)
# a
# b
# c
v = Cls()
print(v.__next__()) # a
print(v.__next__()) # b
print(v.__next__()) # c
print(v.__next__()) # StopIteration:
v = Cls()
print(next(v)) # a
print(next(v)) # b
print(next(v)) # c
print(next(v)) # StopIteration:
<next()>
class Cls:
data = ['a', 'b', 'c']
index = 0
def __next__(self):
if self.index < len(self.data):
i = self.index
self.index += 1
return self.data[i]
raise StopIteration
v = Cls()
print(v) # <__main__.Cls object at 0x000001FCD8360440>
# v = v.__iter__() # AttributeError: 'Cls' object has no attribute '__iter__'
# v = iter(v) # TypeError: 'Cls' object is not iterable
# for x in v: # TypeError: 'Cls' object is not iterable
# print(x)
print(v.__next__()) # a
print(v.__next__()) # b
print(v.__next__()) # c
print(v.__next__()) # StopIteration:
v = Cls()
print(next(v)) # a
print(next(v)) # b
print(next(v)) # c
print(next(v)) # StopIteration:
*__next__()
can be the generator with one or more yield
statement.
class Cls:
data = ['a', 'b', 'c']
index = 0
def __next__(self):
if self.index < len(self.data):
i = self.index
self.index += 1
yield self.data[i]
# yield from self.data[i]
raise StopIteration
v = Cls()
print(v) # <__main__.Cls object at 0x000001FCD2EE4E60>
print(v.__next__().__next__()) # a
print(v.__next__().__next__()) # b
print(v.__next__().__next__()) # c
print(v.__next__().__next__()) # RuntimeError: generator raised StopIteration
v = Cls()
print(next(next(v))) # a
print(next(next(v))) # b
print(next(next(v))) # c
print(next(next(v))) # RuntimeError: generator raised StopIteration
<iter()>
class Cls:
data = ['a', 'b', 'c']
index = 0
def __iter__(self):
return self
v = Cls()
print(v) # <__main__.Cls object at 0x000001FCD6888F80>
v = v.__iter__() # It gets an element but it's not necessary.
print(v) # <__main__.Cls object at 0x000001FCD6888F80>
# v = iter(v) # TypeError: iter() returned non-iterator of type 'Cls'
# for x in v: # TypeError: iter() returned non-iterator of type 'Cls'
# print(x)
# print(v.__next__())
# AttributeError: 'Cls' object has no attribute '__next__'
# print(next(v)) # TypeError: 'Cls' object is not an iterator
*__iter__()
can be the normal function which returns 'Hello'
.
class Cls:
def __iter__(self):
return 'Hello'
v = Cls()
print(v) # <__main__.Cls object at 0x000001FCD2EE4E60>
v = v.__iter__() # It gets an element to print.
print(v)
# Hello
v = Cls()
v = iter(v) # TypeError: iter() returned non-iterator of type 'list'
*__iter__()
can be the generator with one or more yield
statement.
class Cls:
def __iter__(self):
return iter(['a', 'b', 'c'])
# def __iter__(self): # It's a generator.
# yield 'a' # It gets the same result.
# yield 'b'
# yield 'c'
# def __iter__(self): # It's a generator.
# yield from ['a', 'b', 'c'] # It gets the same result.
v = Cls()
print(v) # <__main__.cls object at 0x000001FCD1A14E60>
# It gets an element but it's not necessary for a `for` statement.
v = v.__iter__()
print(v) # <list_iterator object at 0x000001FCD1C42EF0>
for x in v:
print(x)
v = Cls()
v = v.__iter__() # It gets an element for `__next__()`.
print(v.__next__()) # a
print(v.__next__()) # b
print(v.__next__()) # c
print(v.__next__()) # StopIteration:
v = Cls()
v = iter(v) # It gets an element for `next()`.
print(next(v)) # a
print(next(v)) # b
print(next(v)) # c
print(next(v)) # StopIteration: