可变基础架构:实现自定义“处理程序”的最佳方式

时间:2012-12-23 16:49:05

标签: python variables plugins architecture

我正在为数字生活助手创建一个基础设施(有点像Siri)。应用程序应该是高度可扩展的,使用Python编写的插件。整个系统共享一个变量树。变量不是使用Python类型存储的,而是使用自定义的“变量”类型。变量有getvalue和setvalue-methods。你可以做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)。

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

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

其他项目如何做到这一点?是否有一些其他项目我可以查看该项目是如何做到这一点的?

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

从阅读你的问题来看,听起来变量代表你的层次结构中包含可变值的节点,所以我同意将Variable子类化以实现获取其值的不同机制似乎是不对的。

忽略数据结构和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中组合搜索和设置操作。 (路径,价值)。可能值得研究使用库中的树数据结构而不是重新发明它。

希望这会给你一些想法!