*Memo:
- My post explains an iterator (2) and the iterator with copy and sorted().
- 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 the set with copy.
- My post explains a dictionary (1).
- My post explains a string.
- My post explains a bytes.
- My post explains a bytearray.
An iterator:
- is the collection of zero or more elements which can return an element one by one:
- Whether it's ordered or unordered, what type of an iterator it's, whether duplicated elements it can have and how many mixed types it can have all depend on the base type of an iterator.
- can be huge with low memory usage so it doesn't get
MemoryError
. - is immutable so it cannot be changed.
- has
__iter__()
and__next__()
. - can be iterated with a
for
statement. - can be unpacked with an assignment and
for
statement, function and*
but not with**
. - isn't
False
even if it's empty. - can be checked if a specific element is or isn't in it with
in
keyword ornot
andin
keyword respectively. - can be checked if it is or isn't referred to by two variables with
is
keyword ornot
andis
keyword respectively. - cannot be enlarged with
*
and a number. - can be created by iter() or
__iter__()
with an iterable, a generator, generator comprehension or itertools:- For
iter()
, the words type conversion are also suitable in addition to the word creation.
- For
- can be read by next(),
__next__()
orfor
loop to get each element one by one from the iterator. - cannot be read or changed by indexing or slicing.
- raises
StopIteration:
if there are no elements 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(), set(), frozenset() or more_itertools.ilen() to get the length:
-
more-itertools must be installed with
pip install more-itertools
.
-
more-itertools must be installed with
- 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 one by one from the iterator as shown below:
*Memo:
-
iter()
:- The 1st argument is
object
(Required-Type:Iterable or Callable):- It's for an iterable if
sentinel
isn't set. - It's for a callable if
sentinel
is set. - Don't use
object=
.
- It's for an iterable if
- The 2nd argument is
sentinel
(Optional-Type:Any):- It stops
object(Callable)
ifobject(Callable)
returns the same value as it. - Don't use
sentinel=
.
- It stops
- The 1st argument is
-
__iter__()
has no arguments. -
next()
: -
__next__()
has no arguments.
v = iter([]) # Empty 1D iterator
v = iter([0, 1, 2, 3, 4, 5]) # 1D iterator
v = iter([0, 1, 2, 0, 1, 2]) # 1D iterator
v = iter([0, 1, 2, [3, 4, 5]]) # 2D iterator
v = iter([0, 1, [2, 3, [4, 5]]]) # 3D iterator
# No error
v = iter([1, 1.0, 1.0+0.0j, True])
v = iter(['A', b'A', bytearray(b'A'), 2, 2.3, 2.3+4.5j, True,
[2, 3], (2, 3), {2, 3}, frozenset({2, 3}), {'A':'a'},
range(2, 3), iter([2, 3])])
for v in iter([0, 1, 2]): pass
v1, v2, v3 = iter([0, 1, 2])
v1, *v2, v3 = iter([0, 1, 2, 3, 4, 5])
for v1, v2, v3 in iter([iter([0, 1, 2]), iter([3, 4, 5])]): pass
for v1, *v2, v3 in iter([iter([0, 1, 2, 3, 4, 5]),
iter([6, 7, 8, 9, 10, 11])]): pass
print([*iter([0, 1, *iter([2])]), *iter([3, 4])])
print(*iter([0, 1, *iter([2])]), *iter([3, 4]))
v = iter([x**2 for x in range(6)])
# No error
print(**iter([0, 1, 2, 3, 4]))
v = iter(['A', 'B', 'C']) * 3
# Error
<iter(object) & next(iterator)>:
v = iter([0, 1, 2, 3, 4])
print(v)
# <list_iterator object at 0x000002821F75D240>
print(type(v))
# <class 'list_iterator'>
print(next(v)) # 0
print(next(v)) # 1
print(next(v)) # 2
print(next(v)) # 3
print(next(v)) # 4
print(next(v)) # StopIteration:
<__iter__() & __next__()>:
v = [0, 1, 2, 3, 4].__iter__()
print(v)
# <list_iterator object at 0x000001FCD2883280>
print(v.__next__()) # 0
print(v.__next__()) # 1
print(v.__next__()) # 2
print(v.__next__()) # 3
print(v.__next__()) # 4
print(v.__next__()) # StopIteration:
<iter(object) & next(iterator, default)>:
v = iter([0, 1, 2, 3, 4])
print(v)
# <list_iterator object at 0x000002821F75D240>
print(next(v, 'No value')) # 0
print(next(v, 'No value')) # 1
print(next(v, 'No value')) # 2
print(next(v, 'No value')) # 3
print(next(v, 'No value')) # 4
print(next(v, 'No value')) # No value
<iter(object) & for loop>:
v = iter([0, 1, 2, 3, 4])
print(v)
# <list_iterator object at 0x000001FCD2F90790>
for x in v:
print(x)
# 0
# 1
# 2
# 3
# 4
<iter(object, sentinel) & for loop>:
import random
def get_random_numbers():
return random.randint(0, 9)
v = iter(get_random_numbers, 3)
print(v)
# <callable_iterator object at 0x000001FCD2F376A0>
for x in v:
print(x)
# 7
# 0
# 2
# 9
# 5
An iterator can be iterated with a for
statement as shown below:
for v in iter([0, 1, 2]):
print(v)
# 0
# 1
# 2
An iterator can be unpacked with an assignment and for
statement, function and *
but not with **
as shown below:
v1, v2, v3 = iter([0, 1, 2])
print(v1, v2, v3)
# 0 1 2
v1, *v2, v3 = iter([0, 1, 2, 3, 4, 5])
print(v1, v2, v3) # 0 [1, 2, 3, 4] 5
print(v1, *v2, v3) # 0 1 2 3 4 5
for v1, v2, v3 in iter([iter([0, 1, 2]),
iter([3, 4, 5])]):
print(v1, v2, v3)
# 0 1 2
# 3 4 5
for v1, *v2, v3 in iter([iter([0, 1, 2, 3, 4, 5]),
iter([6, 7, 8, 9, 10, 11])]):
print(v1, v2, v3)
print(v1, *v2, v3)
# 0 [1, 2, 3, 4] 5
# 0 1 2 3 4 5
# 6 [7, 8, 9, 10] 11
# 6 7 8 9 10 11
def func(p1='a', p2='b', p3='c', p4='d', p5='e', p6='f'):
print(p1, p2, p3, p4, p5, p6)
func()
# a b c d e f
func(*iter([0, 1, 2, 3]), *iter([4, 5]))
# 0 1 2 3 4 5
def func(p1='a', p2='b', *args):
print(p1, p2, args)
print(p1, p2, *args)
print(p1, p2, ['A', 'B', *args, 'C', 'D'])
func()
# a b ()
# a b
# a b ['A', 'B', 'C', 'D']
func(*iter([0, 1, 2, 3]), *iter([4, 5]))
# 0 1 (2, 3, 4, 5)
# 0 1 2 3 4 5
# 0 1 ['A', 'B', 2, 3, 4, 5, 'C', 'D']
print([*iter([0, 1, *iter([2])]), *iter([3, 4])])
# [0, 1, 2, 3, 4]
print(*iter([0, 1, *iter([2]), *iter([3, 4])]))
# 0 1 2 3 4
print(**iter([0, 1, 2, 3, 4]))
# TypeError: print() argument after ** must be a mapping, not list_iterator
An empty iterator isn't False
as shown below:
print(bool(iter([]))) # Empty iterator
# True
print(bool(iter([0]))) # iterator
print(bool(iter([iter([])]))) # iterator(Empty iterator)
# True
A list can be checked if a specific element is or isn't in it with in
keyword or not
and in
keyword respectively as shown below:
v = iter(['A', 'B', iter(['C', 'D'])])
print('B' in v)
# True
print('C' in v)
print(['C', 'D'] in v)
print(iter(['C', 'D']) in v)
# False
v = iter(['A', 'B', iter(['C', 'D'])])
print('B' not in v)
# False
print('C' not in v)
print(['C', 'D'] not in v)
print(iter(['C', 'D']) not in v)
# True
A iterator cannot be enlarged with *
and a number as shown below:
v = iter(['A', 'B', 'C']) * 3
print(v)
# TypeError: unsupported operand type(s) for *: 'list_iterator' and 'int'
An iterator can be used with len()
after using list()
, tuple()
, set()
, frozenset()
or more_itertools.ilen()
to get the length as shown below:
*Memo:
-
more-itertools
must be installed withpip install more-itertools
. - An iterator cannot be directly used with
len()
to get the length.
from copy import copy
from more_itertools import ilen
v1 = iter([0, 1, 2, 3, 4])
v2 = copy(v1)
print(len(list(v2)))
# 5
v2 = copy(v1)
print(len(tuple(v2)))
# 5
v2 = copy(v1)
print(len(set(v2)))
# 5
v2 = copy(v1)
print(len(frozenset(v2)))
# 5
v2 = copy(v1)
print(ilen(v2))
# 5
v2 = copy(v1)
print(len(v2))
# TypeError: object of type 'list_iterator' has no len()
An iterator cannot be read or changed by indexing or slicing as shown below:
*Memo:
- A del statement can still be used to remove one or more variables themselves.
v = iter(['a', 'b', 'c', 'd', 'e', 'f'])
print(v[0], v[2:6])
# TypeError: 'list_iterator' object is not subscriptable
v = iter(['a', 'b', 'c', 'd', 'e', 'f'])
v[0] = '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], 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 read and change an iterator, use list() and iter() or __iter__() as shown below:
v = iter(['a', 'b', 'c', 'd', 'e', 'f'])
v = list(v)
v[0] = 'X'
v[2:6] = ['Y', 'Z']
v = iter(v)
v = v.__iter__()
for x in v:
print(x)
# X
# b
# Y
# Z
v = iter(['a', 'b', 'c', 'd', 'e', 'f'])
v = list(v)
del v[0], v[3:5]
v = iter(v)
v = v.__iter__()
for x in v:
print(x)
# b
# c
# d
Top comments (0)