DEV Community

Super Kai (Kazuya Ito)
Super Kai (Kazuya Ito)

Posted on • Edited on

Iterator in Python (5)

Buy Me a Coffee

*Memo:

A generator can create an iterator as shown below:

def gen():
    yield 0
    yield 1
    yield from [2, 3, 4]

print(gen)       # <function func at 0x000001FCD2E3CAE0>
print(type(gen)) # <class 'function'>

v = gen()

print(v)       # <generator object func at 0x00000282207E3CC0>
print(type(v)) # <class 'generator'>

for x in v:
    print(x)
# 0
# 1
# 2
# 3
# 4
Enter fullscreen mode Exit fullscreen mode

A generator comprehension can create a generator's iterator as shown below:

<1D iterator>:

v = (x**2 for x in [0, 1, 2, 3, 4, 5, 6, 7])

for x in v:
    print(x)
# 0
# 1
# 4
# 9
# 16
# 25
# 36
# 49
Enter fullscreen mode Exit fullscreen mode

<2D iterator>:

sample = [[0, 1, 2, 3], [4, 5, 6, 7]]

v = ((y**2 for y in x) for x in sample)

for x in v:
    for y in x:
        print(y)
# 0
# 1
# 4
# 9
# 16
# 25
# 36
# 49
Enter fullscreen mode Exit fullscreen mode

<3D iterator>:

sample = [[[0, 1], [2, 3]], [[4, 5], [6, 7]]]

v = (((z**2 for z in y) for y in x) for x in sample)

for x in v:
    for y in x:
        for z in y:
            print(z)
# 0
# 1
# 4
# 9
# 16
# 25
# 36
# 49
Enter fullscreen mode Exit fullscreen mode

Even a big iterator doesn't get MemoryError as shown below:

v = iter(range(100000000))

print(next(v)) # 0
print(next(v)) # 1
print(next(v)) # 2
print(next(v)) # 3
print(next(v)) # 4
# ...
Enter fullscreen mode Exit fullscreen mode
v = (x for x in range(100000000))

print(next(v)) # 0
print(next(v)) # 1
print(next(v)) # 2
print(next(v)) # 3
print(next(v)) # 4
# ...
Enter fullscreen mode Exit fullscreen mode

An iterator cannot be read by indexing and slicing and changed by indexing, slicing and a del statement as shown below:

*Memo:

  • A del statement cannot remove zero or more elements from an iterator by indexing and slicing but can remove one or more variables themselves.
v = iter(['a', 'b', 'c', 'd', 'e', 'f'])

print(v[1], v[3:5])
print(v[-5], v[-3:-1])
# TypeError: 'list_iterator' object is not subscriptable
Enter fullscreen mode Exit fullscreen mode
v = iter(['a', 'b', 'c', 'd', 'e', 'f'])

v[1] = 'X'
v[-5] = 'X'
v[3:5] = ['Y', 'Z']
v[-3:-1] = ['Y', 'Z']
v[1], v[3:5] = 'X', ['Y', 'Z']
v[-5], v[-3:-1] = 'X', ['Y', 'Z']
# TypeError: 'list_iterator' object does not support item assignment
Enter fullscreen mode Exit fullscreen mode
v = iter(['a', 'b', 'c', 'd', 'e', 'f'])

del v[1], v[3:5]
del v[-5], v[-2:5]
# TypeError: 'list_iterator' object does not support item deletion
Enter fullscreen mode Exit fullscreen mode
v = iter(['a', 'b', 'c', 'd', 'e', 'f'])

del v

print(v)
# NameError: name 'v' is not defined
Enter fullscreen mode Exit fullscreen mode

If you really want to read an iterator by indexing and slicing or change an iterator by indexing, slicing and a del statement, use list() and iter() or __iter__() as shown below:

v = iter(['a', 'b', 'c', 'd', 'e', 'f'])

v = list(v)

print(v[1], v[3:5])
print(v[-5], v[-3:-1])
# b ['d', 'e']

v[1] = 'X'
v[-5] = 'X'
v[3:5] = ['Y', 'Z']
v[-3:-1] = ['Y', 'Z']

v[1], v[3:5] = 'X', ['Y', 'Z']
v[-5], v[-3:-1] = 'X', ['Y', 'Z']

v = iter(v)
v = v.__iter__()

for x in v:
    print(x)
# a
# X
# c
# Y
# Z
# f
Enter fullscreen mode Exit fullscreen mode
v = iter(['a', 'b', 'c', 'd', 'e', 'f'])

v = list(v)

del v[1], v[3:5]
# del v[-5], v[-2:5]

v = iter(v)
v = v.__iter__()

for x in v:
    print(x)
# a
# c
# d
Enter fullscreen mode Exit fullscreen mode

Top comments (0)