[PYTHON] Implement a model with state and behavior

Consider switches (lighting power buttons, elevator floor destination buttons, etc.) as primitive models with state and behavior. The switch has two states, a pressed state ʻon and a non-pressed state ʻoff. Also, the behavior of the switch switch () changes depending on the state. If it is in the pressed state ʻon, it will be in the non-pressed state ʻoff, and if it is not pressed, it will be in the pressed state ʻon`.

example1


class Switch:
    def __init__(self, state="off"):
        self.state = state

    def switch(self):
        if self.state == "on":
            self.state = "off"
        elif self.state == "off":
            self.state = "on"
        else:
            # I wonder whether it should be ValueError().
            raise RuntimeError(self.__class__.__name__ + " has an unexpected state: {}".format(self.state))


switch = Switch()
assert switch.state == "off"
switch.switch()
assert switch.state == "on"
switch.switch()
assert switch.state == "off"
switch.state = True
switch.switch()
-> RuntimeError: Switch has an unexpected state: True

For the possible values (states) of Switch.state, you need to look at the implementation of Switch. For example, using enumerated values to represent states can improve visibility.

example2


from enum import Enum, auto


class SwitchState(Enum):
    ON = auto()
    OFF = auto()


class Switch:
    def __init__(self, state=SwitchState.OFF):
        self.state = state

    def switch(self):
        if self.state == SwitchState.ON:
            self.state = SwitchState.OFF
        elif self.state == SwitchState.OFF:
            self.state = SwitchState.ON
        else:
            raise RuntimeError(self.__class__.__name__ + " has an unexpected state: {}".format(self.state))


switch = Switch(SwitchState.ON)
switch.switch()
switch = Switch("on")  # warning: expected SwitchState type

Also, if the default value of the constructor argument state is set to SwitchState, a warning will be issued for values other than SwitchState. However, unexpected values such as ʻon can be assigned to Switch.state` as follows:

switch.state = True
switch.switch()  # RuntimeError: Switch has an unexpected state: True

You don't notice that an unexpected value was assigned until switch () was called. Therefore, it is easier to send a TypeError when an unexpected value is assigned to Switch.state as shown below.

example2


class Switch:
    def __init__(self, state=SwitchState.OFF):
        self._state = state

    def switch(self):
        if self._state == SwitchState.ON:
            self._state = SwitchState.OFF
        elif self._state == SwitchState.OFF:
            self._state = SwitchState.ON
        else:
            raise RuntimeError(self.__class__.__name__ + " has an unexpected state: {}".format(self._state))

    @property
    def state(self) -> SwitchState:
        return self._state

    @state.setter
    def state(self, value: SwitchState):
        if type(value) is not SwitchState:
            raise TypeError(self.__class__.__name__ + ".state must be SwitchState, but get: {}".format(type(value)))
        self._state = value


switch = Switch(SwitchState.ON)
switch.switch()
switch.state = True  # TypeError: Switch.state must be SwitchState, but get: <class 'bool'>

If you don't want the state of Switch to change from outside the class, make it impossible to set a value in Switch.state.

class Switch:
    def __init__(self, state=SwitchState.OFF):
        self._state = state

    def switch(self):
        if self._state == SwitchState.ON:
            self._state = SwitchState.OFF
        elif self._state == SwitchState.OFF:
            self._state = SwitchState.ON
        else:
            raise RuntimeError(self.__class__.__name__ + " has an unexpected state: {}".format(self._state))

    @property
    def state(self) -> SwitchState:
        return self._state


switch = Switch(SwitchState.ON)
switch.switch()
switch.state = SwitchState.OFF  # Property cannot be set

If you want to change the state of Switch from outside the class, it is better to prepare methodsturn_on (),turn_off ()for state transition rather than surrendering Switch.state to outside the class. In some cases.

class Switch:
    def __init__(self, state=SwitchState.OFF):
        self._state = state

    def switch(self):
        if self._state == SwitchState.ON:
            self.turn_off()
        elif self._state == SwitchState.OFF:
            self.turn_on()
        else:
            raise RuntimeError(self.__class__.__name__ + " has an unexpected state: {}".format(self._state))

    @property
    def state(self) -> SwitchState:
        return self._state

    def turn_on(self):
        self._state = SwitchState.ON
    
    def turn_off(self):
        self._state = SwitchState.OFF


switch = Switch()
switch.turn_off()
assert switch.state == SwitchState.OFF
switch.switch()
assert switch.state == SwitchState.ON

Finally, we will change the implementation based on the addition of functions to Switch later. Until now, it was implemented so that the behavior changes according to the state (method processing differs depending on the state), but it can also be implemented so that the state is represented by the difference in behavior (the state differs depending on the processing difference). it can.

from enum import Enum, auto


class SwitchState(Enum):
    ON = auto()
    OFF = auto()


class Switch:
    def __init__(self, state=SwitchState.OFF):
        self.switch = self.turn_on if state == SwitchState.OFF else self.turn_off

    @property
    def state(self) -> SwitchState:
        return SwitchState.OFF if self.switch == self.turn_on else SwitchState.ON

    def turn_on(self):
        self.switch = self.turn_off

    def turn_off(self):
        self.switch = self.turn_on


switch = Switch(SwitchState.ON)
switch.switch()
assert switch.state == SwitchState.OFF
switch.switch()
assert switch.state == SwitchState.ON

There is no difference in the functionality of Switch, only the implementation is different.

Recommended Posts

Implement a model with state and behavior
Implement a model with state and behavior (3) --Example of implementation by decorator
Implement a discrete-time logistic regression model with stan
Create a 3D model viewer with PyQt5 and PyQtGraph
Make a model iterator with PySide
A memo with Python2.7 and Python3 on CentOS
Implement a Custom User Model in Django
Try TensorFlow RNN with a basic model
Create a stack with a queue and a queue with a stack (from LetCode / Implement Stack using Queues, Implement Queue using Stacks)
Create a Todo app with Django ④ Implement folder and task creation functions
A model that identifies the guitar with fast.ai
Connect Scratch X and Digispark with a bottle
Load caffe model with Chainer and classify images
Building a python environment with virtualenv and direnv
Predict hot summers with a linear regression model
Manage state transitions and communicate with smart meters
Build a virtual environment with pyenv and venv
Launch a web server with Python and Flask
Compile and run Rust with a single command
Solving the Lorenz 96 model with Julia and Python
I implemented "Basics of Time Series Analysis and State Space Model" (Hayamoto) with pystan
Build an image classification model explosively with Azure Custom Vision and implement it with Flask
Try making a simple website with responder and sqlite3
I tried to implement and learn DCGAN with PyTorch
Build a python virtual environment with virtualenv and virtualenvwrapper
Create a native GUI app with Py2app and Tkinter
[# 2] Make Minecraft with Python. ~ Model drawing and player implementation ~
Create a batch of images and inflate with ImageDataGenerator
I made a LINE BOT with Python and Heroku
Build a python virtual environment with virtualenv and virtualenvwrapper
Let's make a Mac app with Tkinter and py2app
I tried to implement Grad-CAM with keras and tensorflow
Implement a model with state and behavior (3) --Example of implementation by decorator
Example of using class variables and class methods
Learn Wasserstein GAN with Keras model and TensorFlow optimization
Take a look at profiling and dumping with Dataflow
[Linux] Create a self-signed certificate with Docker and apache
Build a numerical calculation environment with pyenv and miniconda3
[Day 9] Creating a model
Implement FReLU with tf.keras
A4 size with python-pptx
Model Complexity and Robustness
Model fitting with lmfit
Regression with linear model
Decorate with a decorator
[In-Database Python Analysis Tutorial with SQL Server 2017] Step 5: Training and saving a model using T-SQL
With and without WSGI
Implement the mathematical model "SIR model" of infectious diseases with OpenModelica (example of repeating regulation and deregulation)
A story about developing a machine learning model while managing experiments and models with Azure Machine Learning + MLflow
I tried to implement a basic Recurrent Neural Network model
Save the pystan model and results in a pickle file
Convert RGB and HSV in a differentiable form with PyTorch
[Django] Manage settings like writing in settings.py with a model
A simple interactive music player made with Chuck and OpenPose
As a result of mounting and tuning with POH! Lite
Create a web surveillance camera with Raspberry Pi and OpenCV
Implement the mathematical model "SIR model" of infectious diseases with OpenModelica
Associate Python Enum with a function and make it Callable
[Azure] Create, deploy, and relearn a model [ML Studio classic]
Behavior when giving a list with shell = True in subprocess
Create applications, register data, and share with a single email
Let's create a PRML diagram with Python, Numpy and matplotlib.