*Memos:
- My post explains an iterator (2) and copy.
- My post explains a generator.
- My post explains a class-based iterator with __iter__() and/or __next__().
- My post explains the shallow and deep copy of an iterator.
- My post explains itertools about count(), cycle() and repeat().
- My post explains a list and the list with indexing.
- My post explains a tuple.
- My post explains a set and copy.
- My post explains a dictionary, the dictionary with keying and copy.
- My post explains variable assignment.
An iterator:
- is the object which can return an element one by one to use huge data with low memory usage so it doesn't get
MemoryError
. - is immutable so it cannot be changed.
- has __iter__() and
__next__()
. - can be created by iter() or
__iter__()
with a list, tuple, set, dictionary, iterator, string or range(), by a generator or generator comprehension or by itertools: *Memos:- A generator is the function with one or more
yield
statements. - A
yield
statement isyield
oryield from
. - A generator comprehension is an expression.
- A generator is the function with one or more
- can be accessed by next(), next() or
for
loop to get each value. - cannot be accessed and changed by indexing or slicing.
- raises
StopIteration:
if there is no element to return. - can be continuously used through multiple variables.
- except the one created by a generator or generator comprehension can be copied to refer to the same iterator.
- can be used with len() after using list(), tuple() or set() or with more_itertools.ilen() to get the length. *more-itertools must be installed with
pip install more-itertools
. - cannot be directly used with
len()
to get the length.
An iterator is for huge data so it doesn't get MemoryError
.
iter()
or __iter__()
can create an iterator, then next()
, __next__()
or for
loop can get each element for the iterator as shown below:
*Memos:
-
iter()
: *Memos:- The 1st argument is
object
(Required-Type:iterable
orcallable
) for an iterator ifsentinel
isn't set or a callable ifsentinel
is set. *Don't useobject=
. - The 2nd argument is
sentinel
(Optional) to raise error ifobject
returns the same element assentinel
. *Don't usesentinel=
.
- The 1st argument is
-
__iter__()
has no arguments. -
next()
: *Memos:- The 1st argument is
iterator
(Required-Type:iterable
) for an iterator. *Don't useiterator=
. - The 2nd argument is
default
(Optional) to return its value if a iterator is terminated. *Don't usedefault=
. - Error occurs if default isn't set and if an iterator is terminated.
- The 1st argument is
-
__next__()
has no arguments.
<iter(object) & next(iterator)>
v = iter(['a', 'b', 'c', 'd', 'e'])
print(v)
# <list_iterator object at 0x000002821F75D240>
print(next(v)) # a
print(next(v)) # b
print(next(v)) # c
print(next(v)) # d
print(next(v)) # e
print(next(v)) # StopIteration:
<__iter__() & __next__()>
v = ['a', 'b', 'c', 'd', 'e'].__iter__()
print(v)
# <list_iterator object at 0x000001FCD2883280>
print(v.__next__()) # a
print(v.__next__()) # b
print(v.__next__()) # c
print(v.__next__()) # d
print(v.__next__()) # e
print(v.__next__()) # StopIteration:
<iter(object) & next(iterator, default)>
v = iter(['a', 'b', 'c', 'd', 'e'])
print(v)
# <list_iterator object at 0x000002821F75D240>
print(next(v, 'No value')) # a
print(next(v, 'No value')) # b
print(next(v, 'No value')) # c
print(next(v, 'No value')) # d
print(next(v, 'No value')) # e
print(next(v, 'No value')) # No value
<iter(object) & for loop>
v = iter(['a', 'b', 'c', 'd', 'e'])
print(v)
# <list_iterator object at 0x000001FCD2F90790>
for x in v:
print(x)
# a
# b
# c
# d
# e
<iter(object, sentinel) & for loop>
import random
def get_random_numbers():
return random.randint(1, 10)
v = iter(get_random_numbers, 3)
print(v)
# <callable_iterator object at 0x000001FCD2F376A0>
for x in v:
print(x)
# 10
# 6
# 2
# 1
# 6
An iterator can be used with len()
after using list()
, tuple()
or set()
or with more_itertools.ilen()
to get the length as shown below. *more-itertools
must be installed with pip install more-itertools
:
v = iter(['a', 'b', 'c', 'd', 'e'])
print(len(list(v))) # 5
v = iter(['a', 'b', 'c', 'd', 'e'])
print(len(tuple(v))) # 5
v = iter(['a', 'b', 'c', 'd', 'e'])
print(len(set(v)))
v = iter(['a', 'b', 'c', 'd', 'e'])
print(ilen(v))
An iterator cannot be directly used with len()
to get the length as shown below:
v = iter(['a', 'b', 'c', 'd', 'e'])
print(len(v))
# TypeError: object of type 'list_iterator' has no len()
You cannot access and change an iterator by indexing or slicing because it's immutable as shown below. *A del statement can still be used to remove a variable itself:
v = iter(['a', 'b', 'c', 'd', 'e', 'f'])
v[0] = 'X'
# v[-6] = 'X'
v[2:6] = ['Y', 'Z']
# TypeError: 'list_iterator' object does not support item assignment
v = iter(['a', 'b', 'c', 'd', 'e', 'f'])
del v[0]
# del v[-6]
del v[3:5]
# TypeError: 'list_iterator' object does not support item deletion
v = iter(['a', 'b', 'c', 'd', 'e', 'f'])
del v
print(v) # NameError: name 'v' is not defined
If you really want to access and change an iterator, use list() and iter() or __iter__() as shown below:
v = iter(['a', 'b', 'c', 'd', 'e', 'f'])
v = list(v) # Here
v[0] = 'X'
# v[-6] = 'X'
v[2:6] = ['Y', 'Z']
v = iter(v) # Here
v = v.__iter__() # Here
for x in v:
print(x)
# X
# b
# Y
# Z
v = iter(['a', 'b', 'c', 'd', 'e', 'f'])
v = list(v) # Here
del v[0]
# del v[-6]
del v[3:5]
v = iter(v) # Here
v = v.__iter__() # Here
for x in v:
print(x)
# b
# c
# d