python - 使用 reduce 和装饰器在 Python 中级联函数

标签 python python-2.7 python-decorators method-resolution-order

我有一个名为 render 的方法,它实际上由一个子类实现并像这样调用:

class MyClass(object):

    def __call__(self, *args, **kwargs):

        api_response = self.render(*args, **kwargs)

        return api_response

    def render(self, *args, **kwargs):
        """ This method is implemented by a subclass."""    
        raise NotImplementedError

    def cascade_callables():
        print 'Ask awesome people at stackoverflow for the solution to this problem.'

我有一个可调用列表[c1, c2, c3]。我想在 cascade_callables 方法中做这样的事情,应该是这样的:

def cascade_callables():
    callables = [c1, c2, c3]
    callables.append(self.render)
    self.render = reduce(some_decorator_that_accepts_two_functions, callables)

所以本质上,我正在尝试让我的render 像这样工作而不修改实际的实现:

c1(*args, **kwargs)
c2(*args, **kwargs)
c3(*args, **kwargs)
render(*args, **kwargs)

我试过这样的东西作为我可以在 reduce 中使用的装饰器:

def cascade_modifiers(modifier1, modifier2):

    def cascaded_modifier(self, *args, **kwargs):

        modifier1(self, *args, **kwargs)
        modifier2(self, *args, **kwargs)

    return cascaded_modifier

但是我得到了这个:

TypeError: cascaded_modifier() takes at least 1 argument (0 given)

在 Python 2.7 中使用我在这个问题中尝试解释的范例来解决这个问题的最佳方法是什么?

最佳答案

您遇到的问题是您将新的 render 方法保存在一个实例变量中。这意味着它不会自动将 self 传递给它,因为 Python 的方法绑定(bind)使用描述符协议(protocol),而描述符仅在它们是类变量时才有效。

因此,您可能需要确保所有可调用项都已绑定(bind)(如果它们需要使用 self)并重写 cascaded_modifier 以不期望 自身 参数。您实际上已经传递了原始 render 函数的绑定(bind)版本,所以在这种情况下您不会获得 self 的第二个副本实际上很好!

请注意,如果您使用循环而不是reduce,可以简化cascade_callables。这种方法需要的函数少了一个:

def cascade_callables(self):
    callables = [c1, c2, c3]   # these should be bound methods if they need self
    callables.append(self.render)

    def new_render(*args, **kwargs): # no self parameter here
        for c in callables:
            c(*args, **kwargs)       # nor here

    self.render = new_render

如果由于某种原因你确实需要将 self 传递给可调用对象,并且没有一种实用的方法让它们绑定(bind)方法,你可以做一些不同的事情并使用 来自封闭 cascade_callables 范围的 self 参数:

def cascade_callables(self):
    callables = [c1, c2, c3]   # if these are not bound, we can work around the issue
    old_render = self.render   # this one is bound though so we can't mix it in

    def new_render(*args, **kwargs): # no self parameter here
        for c in callables:
            c(self, *args, **kwargs) # but here we access the enclosing scope's self
        old_render(*args, **kwargs)  # this needs to be called separately in this version

    self.render = new_render

关于python - 使用 reduce 和装饰器在 Python 中级联函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25771266/

相关文章:

python - 检查 Python 中是否存在变量 - 不适用于 self

python - 函数名称在 python 类中未定义

python - 似乎append()添加了变量而不是它们的值

python - 如何为每个函数调用使用带有 Flask-RESTPlus 的装饰器?

python - 如何实时更新图像文件 Pygame?

python - 如何在 python 中获取 `http-equiv`?

python - Mac 上应该有多少个不同的 macOS 系统默认版本的 Python?

python - 列表迭代列表如何在 python 中工作?

python - 在 Python 中使用 Loops 修饰多个导入函数

python - 从实例方法定义的 Jupyter magic