[Tutor] automatic setting of class property when another one changes
Peter Otten
__peter__ at web.de
Thu Sep 15 08:14:33 EDT 2016
ingo wrote:
> Rather stuck with this one, I'd like to automatically (re)set the
> propery "relaystate" when one of the others (Tm, Tset, Th) is set,
> regardless of wether their value has changed.
The easiest way to achieve your goal seems to be a read-only property:
# this creates a class that should be shared by all RelayState instances;
# therefore it belongs on the module level
RelayState = namedtuple('RelayState', ['heat', 'cool'])
# the states are immutable and can safely be defined outside the method
HEAT = rlstate(1, 0)
COOL = rlstate(0, 1)
OFF = rlstate(0, 0)
class Thermostat():
...
@property
def relaystate(self):
logger.debug("GETTER relaystate")
lower = self.Tset - self.Th
upper = self.Tset + self.Th
if self.Tm < lower:
return HEAT
elif self.Tm > upper:
return COOL
else:
return OFF
If that doesn't work (because you want to operate an actual relay, say) you
probably have to trigger a change in the TXXX setters:
class Thermostat():
def __init__(self, Tm=20, Tset=20, Th=0.3):
self._relaystate = None
self.Tm = Tm
self.Tset = Tset
self.Th = Th
def update_relaystate(self):
try:
state = self.calculate_relaystate()
except AttributeError:
pass
else:
self.relaystate = state
@property
def Tm(self):
logger.debug("GETTER Tm")
return self._Tm
@Tm.setter
def Tm(self, value):
logger.debug("SETTER Tm")
self._Tm = value
self.update_relaystate()
...
@property
def relaystate(self):
logger.debug("GETTER relaystate")
return self._relaystate
@relaystate.setter
def relaystate(self, value):
if value != self.relaystate:
logger.debug(
"SWITCHING relaystate from %s to %s",
self.relaystate, value)
self._relaystate = value
def calculate_relaystate(self):
lower = self.Tset-self.Th
upper = self.Tset+self.Th
if self.Tm < lower:
return HEAT
elif self.Tm > upper:
return COOL
else:
return OFF
>
> Ingo
>
> My code so far:
>
> from collections import namedtuple
> import logging
>
> logger = logging.getLogger()
> logger.setLevel(logging.DEBUG)
> stream_handler = logging.StreamHandler()
> stream_handler.setLevel(logging.DEBUG)
> formatter = logging.Formatter(
> '[%(levelname)-8s] %(asctime)s (%(name)-8s) - %(message)s',
> '%Y-%m-%d %H:%M:%S',
> )
> stream_handler.setFormatter(formatter)
> logger.addHandler(stream_handler)
>
>
> class Thermostat():
> def __init__(self, Tm=20, Tset=20, Th=0.3):
> logger.debug("__INIT__")
> self.Tm = Tm
> self.Tset = Tset
> self.Th = Th
> self.relaystate = None
>
> @property
> def Tm(self):
> logger.debug("GETTER Tm")
> return self._Tm
> @Tm.setter
> def Tm(self, value):
> logger.debug("SETTER Tm")
> self._Tm = value
>
> @property
> def Tset(self):
> logger.debug("GETTER Tset")
> return self._Tset
> @Tset.setter
> def Tset(self, value):
> logger.debug("SETTER Tset")
> self._Tset = value
>
> @property
> def Th(self):
> logger.debug("GETTER Th")
> return self._Th
> @Th.setter
> def Th(self, value):
> logger.debug("SETTER Th")
> self._Th = value
>
> @property
> def relaystate(self):
> logger.debug("GETTER relaystate")
> return self._relaystate
> @relaystate.setter
> def relaystate(self, value):
> logger.debug("SETTER relaystate")
> #on init while setting Tm, Tset and Th are not known
> #so relaystate can not be calculated
> try:
> lower = self.Tset-self.Th
> upper = self.Tset+self.Th
> except AttributeError as e:
> logger.debug("SETTER relaystate : %s", e)
> self._relaystate = None
> rlstate = namedtuple('relaystate', ['heat', 'cool'])
> if self.Tm < lower:
> value = rlstate(1,0)
> elif self.Tm > upper:
> value = rlstate(0,1)
> elif self.Tm > lower and self.Tm < upper:
> value = rlstate(0,0)
> self._relaystate = value
>
>
> if __name__ == "__main__":
>
> TS1 = Thermostat()
> TS1.Tset = 44
> print("heat : ",TS1.relaystate.heat,"cool : ",TS1.relaystate.cool)
>
> _______________________________________________
> Tutor maillist - Tutor at python.org
> To unsubscribe or change subscription options:
> https://mail.python.org/mailman/listinfo/tutor
More information about the Tutor
mailing list