1

我利用 PyCLIPS 将 CLIPS 集成到 Python 中。Python 方法在 CLIPS 中使用clips.RegisterPythonFunction(method, optional-name). 由于我要注册几个函数并且想保持代码清晰,所以我正在寻找一个装饰器来进行注册。

现在是这样完成的:

class CLIPS(object):
...
    def __init__(self, data):
        self.data = data
        clips.RegisterPythonFunction(self.pyprint, "pyprint")
    def pyprint(self, value):
        print self.data, "".join(map(str, value))

这就是我想做的事情:

class CLIPS(object):
...
    def __init__(self, data):
        self.data = data
        #clips.RegisterPythonFunction(self.pyprint, "pyprint")
    @clips_callable
    def pyprint(self, value):
        print self.data, "".join(map(str, value))

它保留方法的编码并将它们注册在一个地方。

注意:我在多处理器设置中使用它,其中 CLIPS 进程在一个单独的进程中运行,如下所示:

import clips
import multiprocessing

class CLIPS(object):
    def __init__(self, data):
        self.environment = clips.Environment()
        self.data = data
        clips.RegisterPythonFunction(self.pyprint, "pyprint")
        self.environment.Load("test.clp")
    def Run(self, cycles=None):
        self.environment.Reset()
        self.environment.Run()
    def pyprint(self, value):
        print self.data, "".join(map(str, value))

class CLIPSProcess(multiprocessing.Process):
    def run(self):
        p = multiprocessing.current_process()
        self.c = CLIPS("%s %s" % (p.name, p.pid))
        self.c.Run()

if __name__ == "__main__":
    p = multiprocessing.current_process()
    c = CLIPS("%s %s" % (p.name, p.pid))
    c.Run()
    # Now run CLIPS from another process
    cp = CLIPSProcess()
    cp.start()
4

3 回答 3

1

这样做应该相当简单:

# mock clips for testing
class clips:
    @staticmethod
    def RegisterPythonFunction(func, name):
        print "register: ", func, name

def clips_callable(fnc):
    clips.RegisterPythonFunction(fnc, fnc.__name__)
    return fnc

@clips_callable
def test(self):
    print "test"

test()

编辑:如果在类方法上使用它只会注册未绑定的方法。因此,如果在没有类实例作为第一个参数的情况下调用函数,它将不起作用。因此,这可用于注册模块级函数,但不能用于注册类方法。为此,您必须在__init__.

于 2012-05-16T12:57:18.970 回答
0

mata 提出的优雅解决方案似乎行不通,因为 CLIPS 环境应该在向其注册方法之前进行初始化。
我不是 Python 专家,但从一些搜索来看,inspect.getmembers()hasattr()的组合似乎可以为您解决问题 - 您可以循环类的所有成员,并注册具有该@clips_callable属性的成员到剪辑。

于 2012-05-17T04:43:13.813 回答
0

现在通过使用装饰器设置要在 CLIPS 中注册的方法的属性并在init中使用检查来获取方法并注册它们,它现在可以工作了。也可以使用一些命名策略,但我更喜欢使用装饰器来使注册更加明确。可以在初始化 CLIPS 环境之前注册 Python 函数。这就是我所做的。

import inspect

def clips_callable(func):
    from functools import wraps
    @wraps(func)
    def wrapper(*__args,**__kw):
        return func(*__args,**__kw)
    setattr(wrapper, "clips_callable", True)
    return wrapper

class CLIPS(object):
    def __init__(self, data):
        members = inspect.getmembers(self, inspect.ismethod)
        for name, method in members:
            try:
                if method.clips_callable:
                    clips.RegisterPythonFunction(method, name)
            except:
                pass
...
    @clips_callable
    def pyprint(self, value):
        print self.data, "".join(map(str, value))

为了完整起见,下面包含 test.clp 中的 CLIPS 代码。

(defrule MAIN::start-me-up
    =>
    (python-call pyprint "Hello world")
)

如果有人知道更优雅的方法,请告诉我。

于 2012-05-17T09:48:30.417 回答