Considérez les interrupteurs (boutons d'alimentation pour l'éclairage, boutons de destination à chaque étage de l'ascenseur, etc.) comme des modèles primitifs avec état et comportement.
Le commutateur a deux états, un état enfoncé «on» et un état non pressé «off». De plus, le comportement du commutateur switch ()
change en fonction de l'état. S'il est dans l'état pressé «on», il sera dans l'état non pressé «off», et s'il n'est pas pressé, il sera dans l'état pressé «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
Pour les valeurs (états) possibles de Switch.state
, vous devez regarder l'implémentation de Switch
. Par exemple, l'utilisation de valeurs énumérées pour représenter des états peut améliorer la visibilité.
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
De plus, si la valeur par défaut de l'argument du constructeur «state» est définie sur «SwitchState», un avertissement sera émis pour les valeurs autres que «SwitchState». Cependant, des valeurs inattendues telles que ʻon peuvent être affectées à
Switch.state` comme suit:
switch.state = True
switch.switch() # RuntimeError: Switch has an unexpected state: True
Vous ne remarquez pas qu'une valeur inattendue a été attribuée jusqu'à ce que switch ()
soit appelé. Par conséquent, il est plus facile d'envoyer une TypeError lorsqu'une valeur inattendue est affectée à Switch.state
comme indiqué ci-dessous.
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'>
Si vous ne voulez pas que l'état de Switch
soit changé depuis l'extérieur de la classe, il est impossible de définir une valeur dans 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
Si vous voulez changer l'état de Switch
depuis l'extérieur de la classe, il est préférable de fournir des méthodes turn_on ()
, turn_off ()
pour la transition d'état plutôt que de céder Switch.state
à l'extérieur de la classe. Dans certains cas.
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
Enfin, nous modifierons l'implémentation en fonction de l'ajout de fonctions à Switch
plus tard.
Jusqu'à présent, il était implémenté pour que le comportement change en fonction de l'état (le traitement de la méthode diffère selon l'état), mais il peut aussi être implémenté pour que l'état s'exprime par la différence de comportement (l'état diffère en fonction de la différence de traitement). ça peut.
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
Il n'y a aucune différence dans la fonctionnalité de «Switch», seule l'implémentation est différente.
Recommended Posts