0

我正在为数字生活助手创建一个基础设施(有点像 Siri)。该应用程序应该是高度可扩展的,使用 Python 编写的插件。整个系统共享一个变量树。变量不使用 Python 类型存储,而是使用自定义“变量”类型。变量有 getvalue 和 setvalue 方法。例如,您可以这样做var=Variable();var.setvalue('child1','thisvalue') ,但也可以var.setvalue('child1.child2','othervalue')。要检索一个值var.getvar('child1.child2').getvalue(),也是var1=var.getvar('child1');var1.getvar('child2').getvalue()。Getvar 返回子变量的变量实例,getvalue 不带参数,并返回存储变量的类型。(例如 str 或 int)。

我想实现一个变量实例可以做更多事情的系统:例如,可以创建一个返回当前日期时间的变量,或者从网站获取一些数据。我不想使用像 Twisted 的 Deferred 那样的回调系统。

我曾想过让开发人员只继承 Variable 类,并覆盖 getvalue 和/或 setvalue 和/或 getvar 方法,但是,这并不“正确”。我认为有一个更优雅的解决方案。理想情况下,但不一定,变量的 getvalue 等方法可以在创建后更改/添加。

其他项目如何做到这一点?是否有其他项目我可以研究,看看该项目是如何做这种事情的?

谢谢你的帮助。

4

1 回答 1

1

通过阅读您的问题,听起来变量表示层次结构中包含可变值的节点,因此我同意将变量子类化以实现不同的机制来获取其值似乎是不正确的。

忽略数据结构和 get/set 接口,我建议这种架构:

class Variable(object):

    def __init__(self, value=None):
        if value is not None and not isinstance(value, ValueProducer):
            raise TypeError("Expected a ValueProducer.")
        self.__value = value

    def getValue(self):
        return self.__value.produce() if self.__value else None

    def setValue(self, value):
        if value is not None and not isinstance(value, ValueProducer):
            raise TypeError("Expected a ValueProducer.")
        self.__value = value


class ValueProducer(object):

    def produce(self):
        raise NotImplementedError()


class SimpleValueProducer(ValueProducer):

    def __init__(self, value):
        self.__value = value

    def produce(self):
        return self.__value


class HttpRequestValueProducer(ValueProducer):

    def __init__(self, url, params, method="GET"):
        self.__url = url
        self.__params = params
        self.__method = method

    def produce(self):
        # Implementation omitted.
        return "Stub for HTTP request: " \
             + ", ".join((self.__url, str(self.__params), self.__method)


>>> v1 = Variable(SimpleValue("foo"))
>>> print v1.getValue()
foo

>>> v1.setValue(HttpRequestValue("http://localhost:8080", {"bar": "baz"}))
>>> print v1.getValue()
Stub for HTTP request: http://localhost:8080, {'bar': 'baz'}, GET

>>> v1.setValue("test")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "test3.py", line 13, in setValue
    raise TypeError("Expected a ValueProducer.")
TypeError: Expected a ValueProducer.

>>> v2 = Variable()
>>> print v2.getValue()
None

我为 ValueProducer 使用一个类以及实现其接口的子类的原因是为了提高一些可重用性,尤其是对于需要大量代码来检索的值。

附带说明一下,在您的问题中获取和设置值的路径语法似乎有点尴尬:找到一个节点并直接设置它的值感觉更自然,而不是在 parent.setValue(path,价值)。可能值得研究使用库中的树数据结构,而不是重新发明它。

希望这能给你一些想法!

于 2012-12-24T20:55:19.193 回答