2012-01-11 79 views
2

我想在Python中编写一个简单(轻量级)的RESTful服务器。我曾经碰到过下面的代码从Google有人可以解释这个Python代码吗? (可能使用装饰器)

import web 
import json 
from mimerender import mimerender 

render_xml = lambda message: '<message>%s</message>'%message 
render_json = lambda **args: json.dumps(args) 
render_html = lambda message: '<html><body>%s</body></html>'%message 
render_txt = lambda message: message 

urls = (
    '/(.*)', 'greet' 
) 
app = web.application(urls, globals()) 

class greet: 
    @mimerender(
     default = 'html', 
     html = render_html, 
     xml = render_xml, 
     json = render_json, 
     txt = render_txt 
    ) 
    def GET(self, name): 
     if not name: 
      name = 'world' 
     return {'message': 'Hello, ' + name + '!'} 

if __name__ == "__main__": 
    app.run() 

我不熟悉就行了@mimerender使用的语法。这似乎是一个构造函数和函数装饰的AA怪异组合 - 但是,我所遇到的最新装饰的各种用途通常是这样写的:

def foo(): 
    pass 

def foobar(): 
    pass 

@foo 
@pass 
def some_other_func(): 
    pass 

是什么代码意味着/做的@mimerender节?

回答

6
@expr 
def foo(args): 
    pass 

相当于

def foo(args): 
    pass 
foo = expr(foo) 

expr可以是任何有效的Python表达式,所以这里所发生的是,mimerender(…)返回一个可调用对象(无论是通过被构造​​或通过被一个返回的函数可调用对象)。没有太多的魔法在这里:)

以上调用因此只是

def GET(self, name): 
    if not name: 
     name = 'world' 
    return {'message': 'Hello, ' + name + '!'} 
GET = mimerender(…)(GET) 
+1

对。整个故事可以在这里找到:http://stackoverflow.com/questions/739654/understanding-python-decorators – 2012-01-11 11:12:49

+0

@filmor:你不是指GET = mimerender(GET)? - (用你的foo例子) – 2012-01-11 11:26:24

+0

不,我不知道。这就是它的重点。正如其他人回答的,mimerender是一个函数,它返回一个装饰器。所以表达式'mimerender(...)'(其中'...'是上面给出的参数)*是装饰器,这意味着它不过是一个函数,它接受另一个函数并且(最好)返回一个函数。所以,如果你熟悉数学符号,它就像'mimerender:params - >(func - > func)'。 – filmor 2012-01-11 11:34:55

1

这里发生的事情是mimerender是获得装饰:

@mimerender 
def GET(self, name): 

但也有一些是需要ARGS传递到mimerender,所以他们在那里完成。

mimerender文档字符串,如果你想要一些额外的阅读:

def mimerender(default=None, override_arg_idx=None, override_input_key=None, **renderers): 
    """ 
    Usage: 
     @mimerender(default='xml', override_arg_idx=-1, override_input_key='format', , <renderers>) 
     GET(self, ...) (or POST, etc.) 

    The decorated function must return a dict with the objects necessary to 
    render the final result to the user. The selected renderer will be called 
    with the map contents as keyword arguments. 
    If override_arg_idx isn't None, the wrapped function's positional argument 
    at that index will be removed and used instead of the Accept header. 
    override_input_key works the same way, but with web.input(). 

    Example: 
    class greet: 
     @mimerender.mimerender(
      default = 'xml', 
      override_arg_idx = -1, 
      override_input_key = 'format', 
      xhtml = xhtml_templates.greet, 
      html = xhtml_templates.greet, 
      xml  = xml_templates.greet, 
      json = json_render, 
      yaml = json_render, 
      txt  = json_render, 
     ) 
     def GET(self, param): 
      message = 'Hello, %s!'%param 
      return {'message':message} 
    """ 
1

调用时mimerender将构建并返回使用所提供的参数的装饰功能。返回的装饰器函数然后用于装饰GET方法。

0

你可能被间距误导了装饰的。想象一下,它看起来像这样:

@mimereader(default=html) 
def GET(self, name): 

这会使它更清晰吗?

为了解释,这有什么好做的一个构造函数。相反,这里做的是mimereader是一个返回装饰器的函数,而不是实际的装饰器。该函数接受一系列参数,然后将其“烘烤”到装饰器本身。如果你看一下mimereader的定义,你会发现对普通的装饰器定义有一个额外级别的嵌套函数 - 外层定义并返回装饰器本身。

相关问题