Pro Django阅读笔记: 第二章 第二部分

2009-12-05 23:44

废话不多说, 继续写笔记. :)

函数相关的技巧

参数可变的函数调用

这个部分主要讨论了args和kwargs的应用. 当然, 这两个名字不是绝对的语法规定, 只是约定俗成. 当然, 按照个人习惯, 约定俗成的东西就要遵守...

这个部分不算太过分, 从略了. 不过注意下, 写函数的时候, 如果既有可变长参数又有关键字参数, 排列这些参数的顺序应该是:

  1. 普通参数
  2. 可选参数
  3. 可变长参数
  4. 关键字参数

就像这样:

def complex_function(a, b = None, *args, **kwargs):
"""some more code."""

装饰器

上面的参数可变的函数调用能够在很大程度上改变我们调用函数的行为, 我们能够以此来应付各种未知的情况. 除此之外, 装饰器也是另一种常用的改变函数行为的方法. 装饰器接受一个可调用类型作为参数, 返回一个可调用类型.

装饰器的定义和使用并不复杂, 尤其是使用时能够写成特殊的@标记相信对于熟悉Python的人来说还是很好懂好读的. 下面是一个toy装饰器的定义:

def decorate(func):
print 'Decorating %s...' % func.__name__,
def wrapped(*args, **kwargs):
print "Called wrapped function with args:", args
return func(*args, **kargs)
print 'done!'
return wrapped

# Define a toy function using the decorator.
>>> @decorate
... def test(a, b):
...     return a + b
...
Decorating test... done!
>>> test(13, 72)
Called wrapped function with args: (13, 72)
85

如果我们使用@记号来使用装饰器, 那么我们受到的限制相对会更多些. 我们还可以使用更general的使用装饰器的方法, 虽然看起来会更土一些:

>>> def test(a, b):
...     return a + b
...
>>> test = decorate(test)
Decorating test... done!
>>> test(13, 72)
Called wrapped function with args: (13, 72)
85

我们在Django里面经常会用到django.contrib.auth.decorators里的login_required. 这个装饰器的作用是包裹在一个视图函数的外面, 限制这个视图函数只有已登录的用户能够访问. 我再举另外两个装饰器的例子, 一个是django.contrib.admin.views.decorators里的staff_member_required, 顾名思义, 这个装饰器限制对视图函数的访问只能是已登录的staff. 另一个例子是django.views.decorators.http里面的require_http_methods, 它的作用是限制视图函数只能接受特定的HTTP请求, 例如只能接受POST请求等等. 后一个例子是良好的使用参数的装饰器:

def require_http_methods(request_method_list):
"""
    Decorator to make a view only accept particular request methods.  Usage::

        @require_http_methods(["GET", "POST"])
        def my_view(request):
            # I can assume now that only GET or POST requests make it this far
            # ...

    Note that request methods should be in uppercase.
    """
def decorator(func):
def inner(request, *args, **kwargs):
if request.method not in request_method_list:
return HttpResponseNotAllowed(request_method_list)
return func(request, *args, **kwargs)
return wraps(func)(inner)
return decorator

require_GET = require_http_methods(["GET"])
require_GET.__doc__ = "Decorator to require that a view only accept the GET method."

require_POST = require_http_methods(["POST"])
require_POST.__doc__ = "Decorator to require that a view only accept the POST method."

内省