你如何用三个值建模一个州?

时间:2011-04-18 13:27:25

标签: python data-modeling models modeling

我有一些可以处于三种状态的东西

(比如)打开,关闭,正在运行

我会尝试通过两种方式中的一种来建模它,

is_open = Boolean(default=False)
is_running = Boolean(default=False)

并且在应用程序代码中禁止状态(比如)is_running = True,is_open = False。

我也可以尝试

state=Char(choices=("O", "C", "R"))

其中一种方法更好,有没有更好的方法呢?

编辑:我使用的是Python(和Django) 编辑2:阅读下面的答案后,我想我试图用一种适合持久化到DB的形式模拟Python中的枚举(没有它们)

6 个答案:

答案 0 :(得分:2)

在Python中处理此问题的最简单方法是使用字符串常量。将inspect.getgeneratorstate()添加到Python 3.2时,我们就是这样做的。该函数的可能返回值为:

GEN_CREATED = 'GEN_CREATED'
GEN_RUNNING = 'GEN_RUNNING'
GEN_SUSPENDED = 'GEN_SUSPENDED'
GEN_CLOSED = 'GEN_CLOSED'

创建一个简单的类作为常量的命名空间是另一种常见的选择(但该类的属性应该仍然是字符串而不是整数)。

在Python中,对于常量使用整数而不是字符串的收益最小。你在比较速度方面会有一点损失(但由于散列缓存和其他字符串比较优化而不多)并使用稍多的内存(但不多,因为无论目标类型如何,引用都是相同的大小),但大大简化了调试(因为您不需要将整数代码转换为有意义的状态名称 - 您只需显示字符串值)。

答案 1 :(得分:1)

实际上你只需要两个,因为在你的情况下:

closed = ! open

这取决于三个中的一个或者一个以上只能一次有效,比如开放和一起运行?如果我只允许一个州使用Enumerations

由于这个问题在Python中并不支持Enums我建议看看:How can I represent an 'Enum' in Python?所有前四个答案都很有趣,但我更喜欢第一个和第三个,来自Alexandru Nedelcu:

class State:
    OPEN=1
    CLOSED=2
    RUNNING=3

或者Mark Harrison的答案如下:

OPEN, CLOSED, RUNNING = range(3)

答案 2 :(得分:0)

根据您的语言,您可以使用枚举:

enum DoohickyState
{
    Open,
    Closed,
    Running
}

答案 3 :(得分:0)

难以捉摸的“Tri-boolean”值。我在某个地方见过这个。

enum Bool 
{ 
    True, 
    False, 
    FileNotFound 
};

What is Truth? - TheDailyWTF

答案 4 :(得分:0)

+1表示您可能需要枚举的建议。由于python不支持它们,我可能会定义一个类来封装它。这样您就可以在更新时强制执行规则。至少,它会给你与枚举相同的行为。如果合适,您还可以控制合法的州变更,例如:

class Widget:
    def __init__(self, state="Closed"):
        self.state=state

    def open(self):
        if self.state == "Closed":
            self.state = "Open"
        elif self.state == "Open":
            pass
        else:
            # do whatever if trying to open in "Running" state...

    def close(self):
        # etc.

class ThingContainingWidget:
    def __init__(self):
        self.widget=Widget()

    def doSomethingThatAffectsWidget(self):
        self.widget.close()
        # etc.

根据问题,您可能需要/想要将状态更改逻辑移动到封闭类(例如,如果状态行为也依赖于封闭类的其他属性)。但我可能会在Widget类中保留基本验证(确保值只能打开/关闭/运行)。

有一段时间没有做任何django,但想不出有什么理由不起作用。

第h

答案 5 :(得分:0)

这是一个利用Python“属性”的好地方 - 它允许您以透明的方式将get和set方法绑定到对象属性。

这样,你的方法可以控制你想要的行为,你的代码只需要为你的状态设置True或False:

class Machine(object):
    def __init__(self):
        self.open = False
        self._running = False
        self._closed = False

    def get_running(self):
     return self._running

    def set_running(self, val):
        if not self.open and val:
            raise ValueError("Cannot run if it is closed")
        self._running = True

    running = property(get_running, set_running)

    def get_closed(self):
        return self._closed

    def set_closed(self, val):
        if val:
            self.open = False
            self.running = False
        self._closed = val

    closed = property(get_closed, set_closed)

在python控制台上粘贴它可以快速试驾:

>>> m = Machine()
>>> m.open
False
>>> m.running
False
>>> m.running = True
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 12, in set_running
ValueError: Cannot run if it is closed
>>> m.open = True
>>> m.running = True
>>> m.closed
False
>>> m.closed = True
>>> m.open, m.running
(False, True)
>>>