[Python] How to make a class iterable

Contents This is an explanation article on how to perform iterative processing [^ 1] in a Python class. Each code can be downloaded from the GitHub repository.

[^ 1]: Qiita: Python for statement ~ What is iterable ~

iter_minimum.py


iteration = IterClass(["a", "ab", "abc", "bb", "cc"])
print([v for v in iteration if "a" in v])
# ['a', 'ab', 'abc']
Execution environment
OS Windows Subsystem for Linux
Python version 3.8.5

Solution

It can be implemented by the special methods of the class __iter__ [^ 2] and the yield from syntax [^ 3]. Stores a list or tuple and returns it in order from the beginning when called as an iterative process.

[^ 2]: Life with Python: How to use Python's iterator generation class [^ 3]: blanktar: What is the yield from python3.3

iter_minimum.py


class IterClass(object):
    """
    Iterable class.

    Args:
        values (list[object] or tuple(object)): list of values

    Raises:
        TypeError: @values is not a list/tuple
    """

    def __init__(self, values):
        if not isinstance(values, (list, tuple)):
            raise TypeError("@values must be a list or tuple.")
        self._values = values

    def __iter__(self):
        yield from self._values

Application (combination with __bool__)

In the above example, I don't feel the significance of creating a new class, so I made an advanced version.

Creating the smallest unit

First create the smallest unit ʻUnit` class returned by iterative processing.

iter_advanced.py


class Unit(object):
    """
    The smallest unit.
    """

    def __init__(self, value):
        if not isinstance(value, (float, int)):
            raise TypeError(
                f"@value must be integer or float value, but {value} was applied.")
        self._value = value
        self._enabled = True

    def __bool__(self):
        return self._enabled

    @property
    def value(self):
        """
        float: value of the unit
        """
        return self._value

    def enable(self):
        """
        Enable the unit.
        """
        self._enabled = True

    def disable(self):
        """
        Disable the unit.
        """
        self._enabled = False

ʻUnit has a unique value and state (bool`: True / False).

Creating a Unit:

iter_advanced.py


unit1 = Unit(value=1.0)
#Display value if Unit status is True
if unit1:
    print(unit1.value)
# 1.0

State to False:

iter_advanced.py


# Disable
unit1.disable()
#Display value if Unit status is True
if unit1:
    print(unit1.value)
#No output

State to True:

iter_advanced.py


# Disable
unit1.enable()
#Display value if Unit status is True
if unit1:
    print(unit1.value)
# 1.0

Class to iterate

Create a class Series that stores the information of multiple ʻUnit`s and iterates.

iter_advanced.py


class Series(object):
    """
    A series of units.
    """

    def __init__(self):
        self._units = []

    def __iter__(self):
        yield from self._units

    def add(self, unit):
        """
        Append a unit.

        Args:
            unit (Unit]): the smallest unit

        Raises:
            TypeError: unit is not an instance of Unit
        """
        if not isinstance(unit, Unit):
            raise TypeError("@unit must be a instance of Unit")
        self._units.append(unit)

    def _validate_index(self, num):
        """
        Validate the index number.

        Args:
            num (int): index number of a unit

        Raises:
            TypeError: @num is not an integer
            IndexError: @num is not a valid index number
        """
        if not isinstance(num, int):
            raise TypeError(
                f"@num must be integer, but {num} was applied.")
        try:
            self._units[num]
        except IndexError:
            raise IndexError(f"@num must be under {len(self._units)}")

    def enable(self, num):
        """
        Enable a unit.

        Args:
            num (int): index of the unit to be enabled

        Raises:
            TypeError: @num is not an integer
            IndexError: @num is not a valid index number
        """
        self._validate_index(num)
        self._units[num].enable()

    def disable(self, num):
        """
        Disable a unit.

        Args:
            num (int): index of the unit to be disabled

        Raises:
            TypeError: @num is not an integer
            IndexError: @num is not a valid index number
        """
        self._validate_index(num)
        self._units[num].disable()

A function that returns the value of a Unit whose state is True

To check the behavior of the Series class, create a function that returns the value of the Unit whose state is True.

iter_advanced.py


def show_enabled(series):
    """
    Show the values of enabled units.
    """
    if not isinstance(series, Series):
        raise TypeError("@unit must be a instance of Series")
    print([unit.value for unit in series if unit])

Behavior check

Register ʻUnit with Series and display all ʻUnit values.

iter_advanced.py


# Create a series of units
series = Series()
[series.add(Unit(i)) for i in range(6)]
show_enabled(series)
# [0, 1, 2, 3, 4, 5]

If the state of the 5th and 6th Units (values are 4 and 5) is set to False ...

iter_advanced.py


# Disable two units
series.disable(4)
series.disable(5)
show_enabled(series)
# [0, 1, 2, 3]

When the state of the 5th Unit (value is 4) is returned to True ...

iter_advanced.py


# Enable one disabled unit
series.enable(4)
show_enabled(series)
# [0, 1, 2, 3, 4]

Afterword

Thank you for browsing. Thank you for your hard work.

How did you create this article: I used this mechanism in my own Python package CovsirPhy: COVID-19 analysis with phase-dependent SIRs. -PhaseUnit: Period during which the parameter values of the ODE model are constant -PhaseSeries: Infected Number Scenario

Recommended Posts

[Python] How to make a class iterable
How to make a Python package using VS Code
How to make a Japanese-English translation
How to make a slack bot
How to make a crawler --Advanced
How to make a recursive function
How to make a deadman's switch
[Blender] How to make a Blender plugin
How to make a crawler --Basic
[Python] How to make a list of character strings character by character
How to use the __call__ method in a Python class
How to make a Python package (written for an intern)
[Introduction to Python] How to use class in Python?
[Python] How to convert a 2D list to a 1D list
[Python] How to invert a character string
How to get a stacktrace in python
How to use __slots__ in Python class
How to make a Backtrader custom indicator
How to make a Pelican site map
How to run a Maya Python script
How to make a string into an array or an array into a string in Python
How to make a surveillance camera (Security Camera) with Opencv and Python
Slack --APIGateway --Lambda (Python) --How to make a RedShift interactive app
[Python] How to make a matrix of repeating patterns (repmat / tile)
How to install Python
How to install python
How to read a CSV file with Python 2/3
How to create a Python virtual environment (venv)
How to open a web browser from python
How to clear tuples in a list (Python)
How to embed a variable in a python string
How to create a JSON file in Python
How to make a dictionary with a hierarchical structure.
I want to make a game with Python
How to generate a Python object from JSON
Try to make a "cryptanalysis" cipher with Python
How to add a Python module search path
How to make a QGIS plugin (package generation)
How to notify a Discord channel in Python
I read "How to make a hacking lab"
[Blender x Python] How to make an animation
Try to make a dihedral group with Python
How to make Substance Painter Python plugin (Introduction)
[Python] How to draw a histogram in Matplotlib
[Blender x Python] How to make vertex animation
How to make Python faster for beginners [numpy]
How to make Python Interpreter changes in Pycharm
Lark Basics (Python, Lark to make a shell-like guy)
[2020.8 latest] How to install Python
How to convert / restore a string with [] in python
How to install Python [Windows]
Try to make a Python module in C language
[Python] How to draw a line graph with Matplotlib
How to set up a Python environment using pyenv
A road to intermediate Python
Try to make a command standby tool with python
Explain in detail how to make sounds with python
[Python] How to use list 1
How to call a function
How to update Python Tkinter to 8.6
"Cython" tutorial to make Python explosive: How to parse an Enum class defined in C ++ code into a Python Enum.