从一个枚举状态转移到另一个状态并循环通过

时间:2016-04-24 20:24:41

标签: python enums

我只是有3个模式的枚举器ledOn,ledBlink,ledOFF我有一个可变模式,可以跟踪特定对象的模式。所以例如我有一个LED启动模式ledOn我想例如在5秒后移动到下一个元素,然后ledBlink然后到ledOFF然后循环到ledON有一个简单的方法来实现这样的事情吗? / p>

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()

3 个答案:

答案 0 :(得分:1)

我只会使用itertools.cycle代替您的枚举:

>>> 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'
>>> 

仅供参考,你可以next(ledModes)ledModes.next(),两者都是一样的。

编辑:您可以使用类似的方法,作为班级的方法:

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

输出:

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

答案 1 :(得分:1)

您当前代码的最简单修复方法是:

  • 更改您的run方法和
  • 添加next_mode方法:
像这样:

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]

答案 2 :(得分:1)

可能是一种矫枉过正的行为:

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

然后:

>>> 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
相关问题