Python:在包装函数中使用*args,**kwargs

Ale*_*der 7 django args wrapper kwargs render-to-response

我正在为Django的render_to_response()编写一个包装函数来添加CSRF处理.

逻辑是:

def some_view (request)
    dictionary = {'context_param': some_param}
    dictionary.update(csrf(request))
    # ... view code here
    return render_to_response("a_template.html", dictionary)
Run Code Online (Sandbox Code Playgroud)

render_to_response()具有以下签名:

def render_to_response(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

我想写透明包装器 - 只需添加一些功能(前面提到过)并保留其他内容.我想我应该写这样的东西:

def csrf_response (request, *args, **kwargs):

    # Here I need to somehow extract dictionary from args or kwargs

    if dictionary is None:
        dictionary = {}
    dictionary.update(csrf(request))

    # And here I somehow need to pass dictionary into render_to_response() fot the furher processing
    return render_to_response(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

所以问题是 - 从args/kwargs中提取所需参数(然后更改它)并将其进一步传递的最佳实践是什么?

render_to_response()的BTW代码似乎有点奇怪.这里是:

def render_to_response(*args, **kwargs):
    """
    Returns a HttpResponse whose content is filled with the result of calling
    django.template.loader.render_to_string() with the passed arguments.
    """
    httpresponse_kwargs = {'mimetype': kwargs.pop('mimetype', None)}
    return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs)
Run Code Online (Sandbox Code Playgroud)

如果有人用所有位置参数调用它,那么kwargs将为空,但mimetype参数将被指定为最后一个位置参数?在这种情况下看起来它的行为是错误的.

wbe*_*rry 6

由于如何render_to_response实现,指定mimetype的唯一方法是使用命名参数.作为位置参数传递的任何内容都将传递给loader.render_to_string.

如何提取某些论点并传递其他论点的方法实际上取决于你正在做什么.没有一种"正确"的方法可以永远这样做.当然,不同的作者有自己的首选惯例.

在你的评论的位置,# Here I need to somehow extract dictionary from args or kwargs你可以直接使用kwargs作为字典,并将args作为元组,因为这正是它们的本质.对于args,你别无选择,只能断言(即假设)每个位置的值的含义.

我个人更喜欢如果你编写的代码知道某些参数的值,它们应该在签名中声明,如下所示:

def spam(session, name, *args, clear=True, **kwargs):
  # do something with session, name, clear
  return eggs(name, *args, **kwargs)  # if eggs requires name
Run Code Online (Sandbox Code Playgroud)