Iterator in Python (2)
Super Kai (Kazuya Ito)

Super Kai (Kazuya Ito) @hyperkai

About: I'm a web developer. Buy Me a Coffee: ko-fi.com/superkai SO: stackoverflow.com/users/3247006/super-kai-kazuya-ito X(Twitter): twitter.com/superkai_kazuya FB: facebook.com/superkai.kazuya

Joined:
Oct 21, 2021

Iterator in Python (2)

Publish Date: Jun 25
0 0

Buy Me a Coffee

*Memos:

iter() or __iter__() can create an iterator with a list, tuple, set, frozenset, dictionary, iterator, string, byte string(bytes or bytearray) or range() as shown below:

v1 = ['A', 'B', 'C', 'D', 'E'] # list
v2 = iter(v1)
v2 = v1.__iter__()

print(v2)
# <list_iterator object at 0x0000026906F3C460>

for x in v2:
    print(x)
# A
# B
# C
# D
# E
Enter fullscreen mode Exit fullscreen mode
v1 = ('A', 'B', 'C', 'D', 'E') # tuple
v2 = iter(v1)
v2 = v1.__iter__()

print(v2)
# <tuple_iterator object at 0x000002821F7695A0>

for x in v2:
    print(x)
# A
# B
# C
# D
# E
Enter fullscreen mode Exit fullscreen mode
v1 = {'A', 'B', 'C', 'D', 'E'} # set
v2 = iter(v1)
v2 = v1.__iter__()

print(v2)
# <set_iterator object at 0x00000282203069C0>

for x in v2:
    print(x)
# E
# D
# A
# C
# B
Enter fullscreen mode Exit fullscreen mode
v1 = frozenset({'A', 'B', 'C', 'D', 'E'}) # frozenset
v2 = iter(v1)
v2 = v1.__iter__()

print(v2)
# <set_iterator object at 0x000001F3BA7B9500>

for x in v2:
    print(x)
# E
# D
# A
# C
# B
Enter fullscreen mode Exit fullscreen mode
v1 = {'name': 'John', 'age': 36, 'gender': 'Male'} # dictionary
v2 = iter(v1)
v2 = iter(v1.keys())
v2 = v1.__iter__()
v2 = v1.keys().__iter__()

print(v2)
# <dict_keyiterator object at 0x0000028220423FB0>

for x in v2:
    print(x)
# name
# age
# gender

v2 = iter(v1.values())
v2 = v1.values().__iter__()

print(v2)
# <dict_valueiterator object at 0x00000282204FEE80>

for x in v2:
    print(x)
# John
# 36
# Male

v2 = iter(v1.items())
v2 = v1.items().__iter__()

print(v2)
# <dict_itemiterator object at 0x00000282202F1670>

for x in v2:
    print(x)
# ('name', 'John')
# ('age', 36)
# ('gender', 'Male')
Enter fullscreen mode Exit fullscreen mode
v1 = 'Hello' # string
v2 = iter(v1)
v2 = v1.__iter__()

print(v2)
# <str_ascii_iterator object at 0x0000026906CEA560>

for x in v2:
    print(x)
# H
# e
# l
# l
# o
Enter fullscreen mode Exit fullscreen mode
v1 = b'Hello' # bytes
v2 = iter(v1)
v2 = v1.__iter__()

print(v2)
# <str_ascii_iterator object at 0x0000026906CEA560>

for x in v2:
    print(x)
# 72
# 101
# 108
# 108
# 111
Enter fullscreen mode Exit fullscreen mode
v1 = bytearray(b'Hello') # bytearray
v2 = iter(v1)
v2 = v1.__iter__()

print(v2)
# <str_ascii_iterator object at 0x0000026906CEA560>

for x in v2:
    print(x)
# 72
# 101
# 108
# 108
# 111
Enter fullscreen mode Exit fullscreen mode
v1 = range(5) # range
v2 = iter(v1)
v2 = v1.__iter__()

print(v2)
# <range_iterator object at 0x000001F954F52150>

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

A generator can create an iterator as shown below:

def func():
    yield 'A'
    yield 'B'
    yield from ['C', 'D', 'E']

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

gen = func()

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

for x in v2:
    print(x)
# A
# B
# C
# D
# E
Enter fullscreen mode Exit fullscreen mode

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

gen = (x.upper() for x in ['a', 'b', 'c', 'd', 'e'])

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

for x in gen:
    print(x)
# A
# B
# C
# D
# E
Enter fullscreen mode Exit fullscreen mode

A huge iterator doesn't get MemoryError as shown below:

gen = (x for x in range(100000000))

print(next(gen)) # 0
print(next(gen)) # 1
print(next(gen)) # 2
# ...
Enter fullscreen mode Exit fullscreen mode

itertools(repeat(), pairwise() and combinations()) can create iterators as shown below:

from itertools import repeat

v = repeat(object='Hello', times=3)

print(v)
# repeat('Hello')

print(type(v))
# <class 'itertools.repeat'>

print(next(v)) # Hello
print(next(v)) # Hello
print(next(v)) # Hello
print(next(v)) # StopIteration:
Enter fullscreen mode Exit fullscreen mode
from itertools import pairwise

v = pairwise('ABCD')
v = pairwise(['A', 'B', 'C', 'D'])

print(v)
# <itertools.pairwise object at 0x000001BE9A1ABF70>

print(next(v)) # ('A', 'B')
print(next(v)) # ('B', 'C')
print(next(v)) # ('C', 'D')
print(next(v)) # StopIteration:
Enter fullscreen mode Exit fullscreen mode
from itertools import combinations

v = combinations(iterable='ABC', r=2)

print(v)
# <itertools.combinations object at 0x000002690700D170>

print(next(v)) # ('A', 'B')
print(next(v)) # ('A', 'C')
print(next(v)) # ('B', 'C')
print(next(v)) # StopIteration:
Enter fullscreen mode Exit fullscreen mode

An iterator can be continuously used through multiple variables as shown below:

v1 = v2 = v3 = iter(['A', 'B', 'C', 'D', 'E']) # Equivalent
                                   # v1 = iter(['A', 'B', 'C', 'D', 'E'])
print(v1)                          # v2 = v1
print(v2)                          # v3 = v2
print(v3)
# <list_iterator object at 0x000002821F75D240>

print(next(v1)) # A
print(next(v2)) # B
print(next(v3)) # C
print(next(v1)) # D
print(next(v2)) # E
print(next(v3)) # StopIteration:
Enter fullscreen mode Exit fullscreen mode

An iterator except the one created by a generator or generator comprehension can be copied as shown below:

*Memos:

  • copy.copy() does shallow copy. *It has no arguments.
  • copy.deepcopy() does deep copy. *It has no arguments.
  • iter() doesn't shallow copy.
  • copy.deepcopy() should be used because it's safe, doing copy deeply while copy.copy() isn't safe, doing copy shallowly.
import copy

v1 = iter(['A', 'B', 'C', 'D', 'E'])

v2 = copy.copy(v1)
v2 = copy.deepcopy(v1)

print(v1) # <list_iterator object at 0x00000200F45D19C0>
print(v2) # <list_iterator object at 0x000002821F75D240>

print(next(v1)) # A
print(next(v2)) # A
print(next(v1)) # B
print(next(v2)) # B
print(next(v1)) # C
print(next(v2)) # C
print(next(v1)) # D
print(next(v2)) # D
print(next(v1)) # E
print(next(v2)) # E
print(next(v1)) # StopIteration:
print(next(v2)) # StopIteration:
Enter fullscreen mode Exit fullscreen mode
import copy

def func():
    yield 'A'
    yield 'B'
    yield from ['C', 'D', 'E']

gen1 = func()

gen2 = copy.copy(gen1)
gen2 = copy.deepcopy(gen1)
# TypeError: cannot pickle 'generator' object
Enter fullscreen mode Exit fullscreen mode
import copy

gen1 = (x.upper() for x in ['A', 'B', 'C', 'D', 'E'])

gen2 = copy.copy(gen1)
gen2 = copy.deepcopy(gen1)
# TypeError: cannot pickle 'generator' object
Enter fullscreen mode Exit fullscreen mode

The variables v1 and v2 refer to the same iterator unless copied as shown below. *is keyword can check if v1 and v2 refer to the same iterator:

import copy

v1 = iter(['A', 'B', 'C', 'D', 'E'])

v2 = v1 # v2 refers to the same iterator as v1.

print(v1) # <list_iterator object at 0x000001FCD6B64DC0>
print(v2) # <list_iterator object at 0x000001FCD6B64DC0>

print(v1 is v2)
# True

v2 = copy.copy(v1) # v2 refers the different iterator from v1.
v2 = copy.deepcopy(v1)

print(v1) # <list_iterator object at 0x000001FCD6B64DC0>
print(v2) # <list_iterator object at 0x000001FCD6B66020>

print(v1 is v2)
# False
Enter fullscreen mode Exit fullscreen mode

sorted() can convert an iterator to a list, then sort the list, then the sorted list is converted to an iterator with iter() as shown below:

*Memos:

  • The 1st argument is iterable(Required-Type:Iterable). *Don't use iterable=.
  • The 2nd argument is key(Optional-Default:None-Type:Callable or NoneType).
  • The 3rd argument is reverse(Optional-Default:False-Type:bool) to reverse the list.
  • sorted() creates a copy. *Be careful, sorted() does shallow copy instead of deep copy as my issue.
import copy

v1 = iter([3, 5, -2, 1, -4])

v2 = sorted(copy.copy(v1))
v2 = sorted(copy.copy(v1), key=None, reverse=False)

print(v2)
# [-4, -2, 1, 3, 5]

v2 = iter(sorted(copy.copy(v1)))

print(next(v2), next(v2), next(v2), next(v2), next(v2))
# -4 -2 1 3 5

v2 = iter(sorted(copy.copy(v1), reverse=True))

print(next(v2), next(v2), next(v2), next(v2), next(v2))
# 5 3 1 -2 -4

v2 = iter(sorted(copy.copy(v1), key=abs))

print(next(v2), next(v2), next(v2), next(v2), next(v2))
# 1 -2 3 -4 5

v2 = iter(sorted(copy.copy(v1), key=abs, reverse=True))

print(next(v2), next(v2), next(v2), next(v2), next(v2))
# 5 -4 3 -2 1
Enter fullscreen mode Exit fullscreen mode
v1 = ("apple", "Banana", "Kiwi", "cherry")

""" Case sensitive sort """
v2 = iter(sorted(v1))

print(next(v2), next(v2), next(v2), next(v2))
# Banana Kiwi apple cherry

""" Case insensitive sort """
v2 = iter(sorted(v1, key=str.upper))
v2 = iter(sorted(v1, key=str.lower))

print(next(v2), next(v2), next(v2), next(v2))
# apple Banana cherry Kiwi

""" Sort by the length of a word """
v2 = iter(sorted(v1, key=len))

print(next(v2), next(v2), next(v2), next(v2))
# Kiwi apple Banana cherry
Enter fullscreen mode Exit fullscreen mode

Comments 0 total

    Add comment