向包装函数添加第二个返回值,而不会失去向后兼容性

时间:2017-12-29 18:37:11

标签: python flask refactoring

在第三方框架中,源响应函数包含如下:

from flask import Response

def wrap_func(func):
    def add_context(*args, **kwargs):
        output_value = func(*args, **kwargs)

        return Response(
            output_value
        )

    return add_context

开发人员可以使用这个装饰器来创建一个类似入口点的自定义函数:

@wrap_function
def hello():
    return '<b>Hello</b>'

框架会创建一个响应并发送它,此功能隐藏在#34;引擎盖下。

现在我需要设置一些Response参数,例如我的函数hello中的Cookie。如果没有包装器更改似乎是不可能的,我决定为框架做出贡献。

我的第一个问题是使用响应参数从包装函数(hello)返回一个可选值,然后在add_context内解析它。注意,向后兼容性很重要,&#34;旧式&#34;函数应该和#34; new&#34;一起使用响应参数。因此,与hello一起,包装器必须支持这样的函数:

@wrap_function
def ping():
    return '<b>Hello</b>', {'cookies': [('te', 'st')]}

但就我而言,这绝对是一项黑客工作。也许有一些最佳实践来实现这样的更改,甚至更好的方法来修改包装函数的返回而不会失去兼容性?

1 个答案:

答案 0 :(得分:0)

最后我决定以简单灵活的方式。现在,包装函数应该像往常一样返回markdown或Response对象,并使用markdown body初始化。然后,在包装器内部,基于isinstance执行不同的操作。

from flask import Response

def wrap_func(func):
    def add_context(*args, **kwargs):
        output_value = func(*args, **kwargs)

        if isinstance(output_value, Response):
            return output_value
        else:
            return Response(
                output_value
            )

    return add_context

虽然在这个最小的示例包装器之外需要修改响应主体,但是在基于CustomResponse创建Response并重新定义所需操作之后,它可以正常工作。