Pasar de un estado de enumeración a otro y pasar por

Simplemente tengo un enumerador con 3 modos ledOn, ledBlink, ledOFF y tengo un modo variable que realiza un seguimiento de los modos para un objeto en particular. Entonces, por ejemplo, tengo un LED que comienza en modo ledOn. Me gustaría, por ejemplo, después de 5 segundos pasar al siguiente elemento que sería ledBlink, luego ledOFF y luego pasar a ledON. ¿Existe una manera fácil de lograr algo como esto?

import time from threading import Thread from enum import Enum class ledController(Thread): ledModes = Enum('ledModes', 'ledON ledBlink ledOFF') def __init__(self, GPIOID, state=False, blinkDuration=2, mode=ledModes.ledON): self.GPIOID = GPIOID self.state = state self.blinkDuration = blinkDuration self.mode = mode self.blinked = False Thread.__init__(self) def run(self): if(self.mode == self.ledModes.ledON): self.ledON() if(self.mode == self.ledModes.ledBlink): self.ledBlink() if(self.mode == self.ledModes.ledOFF): self.ledOFF() time.sleep(self.blinkDuration) self.mode.next() def ledSwitch(self): self.state = not self.state print(self.ledDetails()) def ledON(self): self.state = True print(self.ledDetails()) def ledOFF(self): self.state = False print(self.ledDetails()) def ledBlink(self, duration): self.ledON() print(self.ledDetails()) time.sleep(self.Blinkduration) self.ledOFF() print(self.ledDetails()) time.sleep(self.Blinkduration) def ledDetails(self): return "Thread: "+self.getName()+", LED: "+str(self.GPIOID)+", State: "+str(self.state)+", Mode: "+str(self.mode.name)+", Blink duration: "+str(self.blinkDuration) redLED = ledController(17, blinkDuration = 3) blueLED = ledController(18, mode = ledController.ledModes.ledOFF) redLED.setName('1') blueLED.setName('2') redLED.start() blueLED.start() redLED.join() blueLED.join() 

La solución más fácil para su código actual es:

  • cambiar su método de run , y
  • añade un método next_mode :

al igual que:

 def run(self): while True: set_mode = getattr(self, self.mode) set_mode() time.sleep(self.blinkDuration) self.next_mode() def next_mode(self): self.mode = { self.ledModes.ledON: self.ledModes.ledBlink, self.ledModes.ledBlink: self.ledModes.ledOFF, self.ledModes.ledOff: self.ledModes.ledOn, }[self.mode] 

Solo usaría itertools.cycle en lugar de tu enumeración:

 >>> from itertools import cycle >>> ledModes = cycle(['ledON', 'ledBlink', 'LedOFF']) >>> first = next(ledModes) >>> second = next(ledModes) >>> third = next(ledModes) >>> fourth = next(ledModes) >>> >>> first 'ledON' >>> second 'ledBlink' >>> third 'LedOFF' >>> fourth 'ledON' >>> 

Para su información, puede hacer next(ledModes) o ledModes.next() , ambos están haciendo lo mismo.

EDITAR: Podría usar algo como esto, como método de su clase:

 from itertools import cycle def initialize_cycle(start_mode): states = ['ledON', 'ledBlink', 'ledOFF'] if start_mode not in states: raise ValueError('start_mode invalid') iterable = cycle(states) for _ in states[:states.index(start_mode)]: iterable.next() return iterable test1 = initialize_cycle('ledON') test2 = initialize_cycle('ledOFF') test3 = initialize_cycle('ledBlink') # validation for test in test1, test2, test3: for _ in range(5): print test.next() print '-' * 20 

Salida:

 $ python cycle.py ledON ledBlink ledOFF ledON ledBlink -------------------- ledOFF ledON ledBlink ledOFF ledON -------------------- ledBlink ledOFF ledON ledBlink ledOFF -------------------- 

Probablemente una exageración:

 import itertools class EnumCycler(object): def __init__(self, enum, start_at=None): self.enum = enum self.members = list(enum.__members__.values()) self.start_at = self.members[0] if start_at is None else start_at self.cycles = 0 def __iter__(self): cycle = itertools.cycle(self.members) sanity_check = len(self.members) for value in cycle: if sanity_check: if value != self.start_at: sanity_check -= 1 continue sanity_check = 0 self.cycles += 1 yield value 

Entonces:

 >>> mode = Enum('ledModes', 'ledON ledBlink ledOFF') >>> led_mode_cycler = EnumCycler(mode, start_at=mode.ledOFF) >>> for value in led_mode_cycler: ... print(led_mode_cycler.cycles, value) ... if led_mode_cycler.cycles >= 10: break # infinite loop if we never break off 1 ledModes.ledOFF 2 ledModes.ledON 3 ledModes.ledBlink 4 ledModes.ledOFF 5 ledModes.ledON 6 ledModes.ledBlink 7 ledModes.ledOFF 8 ledModes.ledON 9 ledModes.ledBlink 10 ledModes.ledOFF