Iterator in Python (4)
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 (4)

Publish Date: Jun 25
0 0

Buy Me a Coffee

*Memos:

  • My post explains an iterator (1).
  • My post explains an iterator (2) and copy.
  • My post explains a generator.

You can create a class-based iterator with __iter__() and/or __next__() as shown below:

*Memos:

  • Basically, __iter__() is used to return an iterator.
  • Basically, __next__() is used to return the next element.

<iter() & next()>

class Cls:
    data = ['a', 'b', 'c']
    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)
# a
# b
# c

v = Cls()

print(v.__next__()) # a
print(v.__next__()) # b
print(v.__next__()) # c
print(v.__next__()) # StopIteration:

v = Cls()

print(next(v)) # a
print(next(v)) # b
print(next(v)) # c
print(next(v)) # StopIteration:
Enter fullscreen mode Exit fullscreen mode

<next()>

class Cls:
    data = ['a', 'b', 'c']
    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>

# v = v.__iter__() # AttributeError: 'Cls' object has no attribute '__iter__'
# v = iter(v) # TypeError: 'Cls' object is not iterable

# for x in v: # TypeError: 'Cls' object is not iterable
#     print(x)

print(v.__next__()) # a
print(v.__next__()) # b
print(v.__next__()) # c
print(v.__next__()) # StopIteration:

v = Cls()

print(next(v)) # a
print(next(v)) # b
print(next(v)) # c
print(next(v)) # StopIteration:
Enter fullscreen mode Exit fullscreen mode

*__next__() can be the generator with one or more yield statement.

class Cls:
    data = ['a', 'b', 'c']
    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__()) # a
print(v.__next__().__next__()) # b
print(v.__next__().__next__()) # c
print(v.__next__().__next__()) # RuntimeError: generator raised StopIteration

v = Cls()

print(next(next(v))) # a
print(next(next(v))) # b
print(next(next(v))) # c
print(next(next(v))) # RuntimeError: generator raised StopIteration
Enter fullscreen mode Exit fullscreen mode

<iter()>

class Cls:
    data = ['a', 'b', 'c']
    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: # TypeError: iter() returned non-iterator of type 'Cls'
#     print(x)

# print(v.__next__())
# AttributeError: 'Cls' object has no attribute '__next__'

# print(next(v)) # TypeError: 'Cls' object is not an iterator
Enter fullscreen mode Exit fullscreen mode

*__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'
Enter fullscreen mode Exit fullscreen mode

*__iter__() can be the generator with one or more yield statement.

class Cls:
    def __iter__(self):
        return iter(['a', 'b', 'c'])

    # def __iter__(self): # It's a generator.
    #     yield 'a'       # It gets the same result.
    #     yield 'b'
    #     yield 'c'

    # def __iter__(self):            # It's a generator.
    #     yield from ['a', 'b', 'c'] # 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:
Enter fullscreen mode Exit fullscreen mode

Comments 0 total

    Add comment