为什么我的MultiAdapter无法注册?

时间:2015-02-21 20:40:47

标签: python zope zope.component

我目前正在尝试使用ZCA,但我遇到了一些麻烦。下面的脚本定义了一个IFuncttion接口,用于创建可链接的函数对象(即monad)。

在此示例中,我尝试创建一个简单的编写器monad作为适配器,但getMultiAdapter正在提升ComponentLookupError。这是为什么?

from zope import component, interface


class IFunction(interface.Interface):
    name = interface.Attribute('Name of the function object')

    def __call__(*args, **kw):
        """Call the function"""


class Function(object):
    name = ''
    interface.implements(IFunction)

    def __call__(self, *args, **kw):
        return self.run(*args, **kw)

    def run(self, *args, **kw):
        raise NotImplementedError


class MWriter(object):
    component.adapts(IFunction, IFunction)
    interface.implements(IFunction)

    def __init__(self, prv, nxt):
        self.prev, self.next = prv, nxt

    def bind(self, x, log=None):
        log = log or []
        result, line = self.prev(x)
        log.append(line)
        return self.next(result, log)

    def __call__(self, *args, **kw):
        return self.bind(*args, **kw)


class AddOne(Function):
    name = 'addone'

    def run(self, x):
        return x + 1


class MulTwo(Function):
    name = 'multwo'

    def run(self, x):
        return x * 2

component.provideAdapter(MWriter)
print component.getMultiAdapter((AddOne(), MulTwo()), MWriter)(11, [])

1 个答案:

答案 0 :(得分:1)

您应该传递要查看component.getMultiAdapter()的适配器。该函数的第二个参数是用于命名适配器的名称,但您的注册没有使用名称。

只需删除第二个参数:

>>> component.getMultiAdapter((AddOne(), MulTwo()))
<__main__.MWriter object at 0x1072516d0>

不幸的是,调用 MWriter()仍然失败,因为您希望self.prev()返回一个元组:

result, line = self.prev(x)

AddOne()只返回一个整数:

class AddOne(Function):
    name = 'addone'

    def run(self, x):
        return x + 1

所以你得到一个例外:

>>> component.getMultiAdapter((AddOne(), MulTwo()))(11)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 37, in __call__
  File "<string>", line 32, in bind
TypeError: 'int' object is not iterable

也许您希望每个Function()都返回名称以及结果:

class Function(object):
    name = ''
    interface.implements(IFunction)

    def __call__(self, *args, **kw):
        return self.run(*args, **kw), self.name

    def run(self, *args, **kw):
        raise NotImplementedError

但随后调用self.next()失败,因为它不接受传入的额外log参数。