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 |
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
__bool__
)In the above example, I don't feel the significance of creating a new class, so I made an advanced version.
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
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()
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])
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]
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