[GO] Learn the design pattern "Iterator" in Python

As a material for learning GoF design patterns, the book "Introduction to Design Patterns Learned in the Augmented and Revised Java Language" seems to be helpful. However, since the examples taken up are based on JAVA, I tried the same practice in Python to deepen my understanding.

■ Iterator (Iterator pattern)

The Iterator pattern is one of the design patterns defined by GoF (Gang of Four; 4 gangs). The purpose is to provide an iterator that does not depend on the internal specifications of the container by making the means for enumerating the elements of the container object independent.

UML class and sequence diagram W3sDesign_Iterator_Design_Pattern_UML.jpg UML class diagram iterator.png (The above is quoted from Wikipedia)

□ Memorandum

Iterator pattern seems to be for performing the process of pointing to it in order and scanning the whole when a lot of things are gathered. ʻIterator` is sometimes called ** iterator ** in Japanese. You often see it when you're involved in Python programming.

■ "Iterator" sample program

I would like to actually run a sample program that utilizes the Iterator pattern and check the following behavior.

--Add ʻAroun d the World in 80 daysbooks to the bookshelf --AddBiblebooks to the bookshelf --AddCinderellabooks to the bookshelf --Add theDaddy-Long-Legs` book to the bookshelf --Display the titles of books currently on the bookshelf

$ python Main.py 
Aroun d the World in 80 days
Bible
Cinderella
Daddy-Long-Legs

■ Details of sample program

Similar code has been uploaded to the Git repository. https://github.com/ttsubo/study_of_design_pattern/tree/master/Iterator/step1

--Directory structure

.
├── Main.py
└── iterator
    ├── __init__.py
    ├── aggregate.py
    ├── book.py
    └── iterator.py

(1) The role of Iterator

It is the role that defines the interface that scans the elements in order. In the sample program, the ʻIterator` class serves this role.

iterator/iterator.py


from abc import ABCMeta, abstractmethod

class Iterator(metaclass=ABCMeta):
    @abstractmethod
    def hasNext(self):
        pass

    @abstractmethod
    def next(self):
        pass

(2) The role of Concrete Iterator

It is the role that actually implements the interface defined by the role of ʻIterator. In the sample program, the BookShelfIteratorclass serves this role. This role must have the information needed to scan. In the sample program, the instance of theBookShelf class is remembered by the instance variable self.__ bookShelf, and the book of interest is remembered by the instance variable self.__index`.

iterator/book.py


from iterator.iterator import Iterator

...(snip)

class BookShelfIterator(Iterator):
    def __init__(self, bookShelf):
        self.__bookShelf = bookShelf
        self.__index = 0

    def hasNext(self):
        return True if self.__index < self.__bookShelf.getLength() else False

    def next(self):
        book = self.__bookShelf.getBookAt(self.__index)
        self.__index += 1
        return book

(3) The role of Aggregate

ʻIterator This is the role that defines the interface that creates the role. The interface is an abstraction method that creates "a person who scans the elements I have in order". In the sample program, the ʻAggregate class serves this role.

iterator/aggregate.py


from abc import ABCMeta, abstractmethod

class Aggregate(metaclass=ABCMeta):
    @abstractmethod
    def iterator(self):
        pass

(4) The role of Concrete Aggregate

ʻAggregate This is the role that actually implements the interface defined by the role. Create a concrete instance of the ʻIterator role, that is, the Concrete Iterator role. In the sample program, the BookShelf class serves this role.

iterator/book.py


from iterator.aggregate import Aggregate

...(snip)

class BookShelf(Aggregate):
    def __init__(self, maxSize):
        self.__last = 0
        self.__books = [None] * maxSize

    def getBookAt(self, index):
        return self.__books[index]

    def append(self, book):
        self.__books[self.__last] = book
        self.__last += 1

    def getLength(self):
        return self.__last

    def iterator(self):
        return BookShelfIterator(self)

(5) The role of Client

In the sample program, the startMain method serves this role.

Main.py


from iterator.book import Book, BookShelf

def startMain():
    bookShelf = BookShelf(4)
    bookShelf.append(Book(name="Aroun d the World in 80 days"))
    bookShelf.append(Book(name="Bible"))
    bookShelf.append(Book(name="Cinderella"))
    bookShelf.append(Book(name="Daddy-Long-Legs"))
    it = bookShelf.iterator()
    while it.hasNext():
        book = it.next()
        print(book.getName())

if __name__ == '__main__':
    startMain()

(6) Other

Manage book titles.

iterator/book.py


class Book(object):
    def __init__(self, name):
        self.__name = name

    def getName(self):
        return self.__name

□ Memorandum (Try using Python iterator!)

In Python programming, I often see iterators. For information on Python iterators, refer to this Web article "[Introduction to Python] What is an Iterator?". .. In addition, when defining a new class, it seems that the following requirements must be met in order to have the properties of an iterator.

--Has a __iter__ method that returns itself --Has a __next__ method that returns the values of the element columns that you manage one by one --In the __next__ method, aStopIteration exception is raised when the elements are exhausted.

I would like to rewrite the sample program with ** Python Iterator **. Similar code has been uploaded to the Git repository. https://github.com/ttsubo/study_of_design_pattern/tree/master/Iterator/step2

iterator/book.py


class Book(object):
    def __init__(self, name):
        self.__name = name

    def getName(self):
        return self.__name


class BookShelf(object):
    def __init__(self):
        self.__books = []

    def append(self, book):
        self.__books.append(book)

    def __iter__(self):
        self.__index = 0
        return self

    def __next__(self):
        if self.__index >= len(self.__books):
            raise StopIteration()
        book = self.__books[self.__index]
        self.__index += 1
        return book

Main.py


from iterator.book import Book, BookShelf

def startMain():
    bookShelf = BookShelf()
    bookShelf.append(Book(name="Aroun d the World in 80 days"))
    bookShelf.append(Book(name="Bible"))
    bookShelf.append(Book(name="Cinderella"))
    bookShelf.append(Book(name="Daddy-Long-Legs"))
    for book in bookShelf:
        print(book.getName())

if __name__ == '__main__':
    startMain()

It's a lot simpler. Let's move it.

$ python Main.py 
Aroun d the World in 80 days
Bible
Cinderella
Daddy-Long-Legs

Since it is the same as the first operation result, it is completed for the time being.

■ Reference URL

-[Finishing "Introduction to Design Patterns Learned in Java Language" (Not)](https://medium.com/since-i-want-to-start-blog-that-looks-like-men-do/java Introduction to Design Patterns Learned in Language-Finishing-Not-2cc9b34a30b2) -Web article "[Introduction to Python] What is an iterator?"

Recommended Posts

Learn the design pattern "Iterator" in Python
Learn the design pattern "Prototype" in Python
Learn the design pattern "Builder" in Python
Learn the design pattern "Observer" in Python
Learn the design pattern "Proxy" in Python
Learn the design pattern "Command" in Python
Learn the design pattern "Visitor" in Python
Learn the design pattern "Bridge" in Python
Learn the design pattern "Mediator" in Python
Learn the design pattern "Decorator" in Python
Learn the design pattern "Strategy" in Python
Learn the design pattern "Composite" in Python
Learn the design pattern "State" in Python
Learn the design pattern "Adapter" in Python
Learn the design pattern "Abstract Factory" in Python
Learn the design pattern "Template Method" in Python
Learn the design pattern "Factory Method" in Python
Learn the design pattern "Chain of Responsibility" in Python
Learn the design pattern "Singleton" with Python
Learn the design pattern "Facade" with Python
Implement the Singleton pattern in Python
Singleton pattern in Python
Iterator pattern in Java
Download the file in Python
Learn cumulative sum in Python
I wrote a design pattern in kotlin, Iterator edition
Design Patterns in Python: Introduction
Learn exploration in Python # 1 Full exploration
Python Design Pattern --Template method
Getting the arXiv API in Python
Python in the browser: Brython's recommendation
Save the binary file in Python
Get the desktop path in Python
Get the script path in Python
In the python command python points to python3.8
Split iterator into chunks in python
Hit the web API in Python
I wrote the queue in Python
Calculate the previous month in Python
Examine the object's class in python
Get the desktop path in Python
Get the host name in Python
Access the Twitter API in Python
The first step in Python Matplotlib
I wrote the stack in Python
Master the weakref module in Python
Learn the basics of Python ① Beginners
Load the remote Python SDK in IntelliJ
Try using the Wunderlist API in Python
Check the behavior of destructor in Python
[Python Kivy] About changing the design theme
Try using the Kraken API in Python
Write the test in a python docstring
[Gang of Four] Design pattern learning --Iterator
OR the List in Python (zip function)
GoF design pattern from the problem 2. Structure
Display Python 3 in the browser with MAMP
Tweet using the Twitter API in Python
Check if the URL exists in Python
Run the Python interpreter in a script
The result of installing python in Anaconda