2013-07-01 26 views
0

免責聲明:我顯然很新的裝飾如何調用基於參數的具體功能,裝飾機

創建和裝飾在Python功能是相當簡單和直接,這excellent answer(具有最讚的),給出了一個很好的介紹,並展示瞭如何嵌套裝飾器。那麼這一切都很好,很棒。但是我還沒有弄清楚有多少(python)-web-frameworks(flask,django等)可以調用,我只能猜到的是裝飾函數基於參數傳遞給在裝飾

一個例子(使用瓶,但在許多類似的框架),向你展示我的意思。

@application.route('/page/a_page') 
def show_a_page(): 
    return html_content 

@application.route('/page/another_page') 
def show_another_page(): 
    return html_content 

現在,如果我做出mysite.com/page/a_page瓶的請求以某種方式推斷出它應該叫show_a_page,並ofcourse也是如此show_another_page如果請求是mysite.com/page/a_page

我不知道我怎麼會去在我自己的項目中實現類似的功能?

我假設存在類似於使用dir(module_name)提取有關裝修(?)每個功能的信息的東西嗎?

+0

我不知道我是否理解:你是問如何在Flask上添加一些功能,或者如何在自己的項目中編寫類似的東西? –

+0

我想在自己的項目中做類似的事情,我會澄清我的問題。 –

+1

你看過燒瓶源代碼嗎?這很容易遵循,它不涉及太多的功能表,它需要一些字符串/命令和映射到一個函數來調用。 – sean

回答

0

一個裝飾用做一個函數到底是怎麼回事吧。它可以將其包裝在另一個函數中,爲其屬性添加一些元信息,甚至將其存儲在字典中。

這裏是你如何能多種功能保存到一個字典,以後可以用來查找這些函數的例子:

function_table = {} 

def add_to_table(name): 
    def dec(func): 
     def inner_func(*args, **kwargs): 
      return func(*args, **kwargs) 
     function_table[name] = inner_func 
     return inner_func 
    return dec 

@add_to_table("my_addition_function") 
def myfunction(a, b): 
    return a + b 

@add_to_table("my_subtraction_function") 
def myfunction2(a, b): 
    return a - b 

print myfunction(1, 3) 
# 4 
print function_table["my_addition_function"](1, 4) 
# 5 
print function_table["my_subtraction_function"](1, 4) 
# -3 

這是一個什麼樣瓶是做一個非常簡單的版本:存儲根據正在使用的路徑調用哪些函數表。

0

沒有理由一個裝飾不能做其他的東西,除了包裝功能

>>> def print_stuff(stuff): 
...  def decorator(f): 
...   print stuff 
...   return f 
...  return decorator 
... 
>>> @print_stuff('Hello, world!') 
... def my_func(): 
...  pass 
... 
Hello, world! 

在這個例子中,我們簡單地打印出傳給裝飾的構造方法時,我們定義函數的參數。請注意,我們印着「你好,世界!」沒有實際調用my_func - 這是因爲當我們構建了裝飾,而不是在裝飾本身中發生打印。

發生了什麼事,application.route本身不是裝飾者。相反,它是採用一個路線,併產生將被應用到該視圖的功能,以及在該通路登錄視圖函數裝飾器的功能。在燒瓶中,將裝飾構造有權訪問途徑和查看功能兩者,所以它可以在應用對象上路線寄存器視圖函數。如果你有興趣,你可以看看在燒瓶源代碼Github上:

https://github.com/mitsuhiko/flask/blob/master/flask/app.py

0

下面是一個粗略的例子,使用BeautifulSoup,它建立在David Robinson的答案上。裝飾器使用傳遞給它的字符串作爲對應於函數的字典的關鍵字。這是通過關鍵字參數傳遞給它所調用的裝飾函數。

import os 
import sys 

# Import System libraries 
from copy import deepcopy 

# Import Custom libraries 
from BeautifulSoup import BeautifulSoup, Tag 

page_base_str = \ 
''' 
<!doctype html> 
<html> 
<head> 
    <title>Example Domain</title> 

    <meta charset="utf-8" /> 
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> 
    <meta name="viewport" content="width=device-width, initial-scale=1" /> 
    <style type="text/css"> 
    body { 
     background-color: #f0f0f2; 
     margin: 0; 
     padding: 0; 
     font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; 

    } 
    div { 
     width: 600px; 
     margin: 5em auto; 
     padding: 50px; 
     background-color: #fff; 
     border-radius: 1em; 
    } 
    a:link, a:visited { 
     color: #38488f; 
     text-decoration: none; 
    } 
    @media (max-width: 700px) { 
     body { 
      background-color: #fff; 
     } 
     div { 
      width: auto; 
      margin: 0 auto; 
      border-radius: 0; 
      padding: 1em; 
     } 
    } 
    </style>  
</head> 

<body> 
<div> 
    <h1>Example Domain</h1> 
    <div id="body"> 
     <p>This domain is established to be used for illustrative examples in documents. You may use this 
     domain in examples without prior coordination or asking for permission.</p> 
     <p><a href="http://www.iana.org/domains/example">More information...</a></p> 
    </div> 
</div> 
</body> 
</html> 
''' 
page_base_tag = BeautifulSoup(page_base_str) 

def default_gen(*args): 
    return page_base_tag.prettify() 

def test_gen(**kwargs): 
    copy_tag = deepcopy(page_base_tag) 

    title_change_locations = \ 
    [ 
     lambda x: x.name == u"title", 
     lambda x: x.name == u"h1" 
    ] 
    title = kwargs.get("title", "") 
    if(title): 
     for location in title_change_locations: 
      search_list = copy_tag.findAll(location) 
      if(not search_list): 
       continue 
      tag_handle = search_list[0] 
      tag_handle.clear() 
      tag_handle.insert(0, title) 

    body_change_locations = \ 
    [ 
     lambda x: x.name == "div" and set([(u"id", u"body")]) <= set(x.attrs) 
    ] 
    body = kwargs.get("body", "") 
    if(body): 
     for location in body_change_locations: 
      search_list = copy_tag.findAll(location) 
      if(not search_list): 
       continue 
      tag_handle = search_list[0] 
      tag_handle.clear() 
      tag_handle.insert(0, body) 

    return copy_tag.prettify() 

page_gens = \ 
{ 
    "TEST" : test_gen 
} 

def page_gen(name = ""): 
    def dec(func): 
     def inner_func(**kwargs): 
      kwargs["PAGE_FUNC"] = page_gens.get(name, default_gen) 
      return func(**kwargs) 
     return inner_func 
    return dec 

@page_gen("TEST") 
def test_page_01(**kwargs): 
    content = kwargs["PAGE_FUNC"](title = "Page 01", body = "Page 01 body") 
    return content 

@page_gen("TEST") 
def test_page_02(**kwargs): 
    content = kwargs["PAGE_FUNC"](title = "Page 02", body = "Page 02 body") 
    return content 

@page_gen() 
def a_page(**kwargs): 
    content = kwargs["PAGE_FUNC"]() 
    return content 

print test_page_01() 
print test_page_02() 
print a_page()