*Memo:
- My post explains an iterator (1).
- My post explains an iterator (2) and the iterator with copy and sorted().
- My post explains a generator.
- My post explains the shallow and deep copy of an iterator.
A class-based iterator can be created with __iter__() and/or __next__() as shown below:
*Memo:
- Basically,
__iter__()
is used to return an iterator. - Basically,
__next__()
is used to return the next element.
<__iter__() & __next__()>:
class Cls:
data = [0, 1, 2]
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)
# 0
# 1
# 2
v = Cls()
print(v.__next__()) # 0
print(v.__next__()) # 1
print(v.__next__()) # 2
print(v.__next__()) # StopIteration:
v = Cls()
print(next(v)) # 0
print(next(v)) # 1
print(next(v)) # 2
print(next(v)) # StopIteration:
<__next__()>:
class Cls:
data = [0, 1, 2]
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>
print(v.__next__()) # 0
print(v.__next__()) # 1
print(v.__next__()) # 2
print(v.__next__()) # StopIteration:
v = Cls()
print(next(v)) # 0
print(next(v)) # 1
print(next(v)) # 2
print(next(v)) # StopIteration:
v = Cls()
v = v.__iter__()
# AttributeError: 'Cls' object has no attribute '__iter__'
v = iter(v)
# TypeError: 'Cls' object is not iterable
for x in v:
print(x)
# TypeError: 'Cls' object is not iterable
*__next__()
can be the generator with one or more yield
statement.
class Cls:
data = [0, 1, 2]
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__()) # 0
print(v.__next__().__next__()) # 1
print(v.__next__().__next__()) # 2
print(v.__next__().__next__()) # RuntimeError: generator raised StopIteration
v = Cls()
print(next(next(v))) # 0
print(next(next(v))) # 1
print(next(next(v))) # 2
print(next(next(v))) # RuntimeError: generator raised StopIteration
<__iter__()>:
class Cls:
data = [0, 1, 2]
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:
print(x)
# TypeError: iter() returned non-iterator of type 'Cls'
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([0, 1, 2])
# def __iter__(self): # It's a generator.
# yield 0 # It gets the same result.
# yield 1
# yield 2
# def __iter__(self): # It's a generator.
# yield from [0, 1, 2] # 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:
Top comments (0)