为什么我的 MultiAdapter 无法注册?

Why is my MultiAdapter failing to register?

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

在这个例子中,我试图创建一个简单的 writer 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, [])

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

只需删除第二个参数:

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

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

result, line = self.prev(x)

AddOne() return 只是一个整数:

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() 到 return 的名称和结果:

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 参数。