国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

Bottle框架中的裝飾器類和描述符應用詳解

2020-02-16 10:31:29
字體:
來源:轉載
供稿:網友

最近在閱讀Python微型Web框架Bottle的源碼,發現了Bottle中有一個既是裝飾器類又是描述符的有趣實現。剛好這兩個點是Python比較的難理解,又混合在一起,讓代碼有些晦澀難懂。但理解代碼之后不由得為Python語言的簡潔優美贊嘆。所以把相關知識和想法稍微整理,以供分享。

正文

Bottle是Python的一個微型Web框架,所有代碼都在一個bottle.py文件中,只依賴標準庫實現,兼容Python 2和Python 3,而且最新的穩定版0.12代碼也只有3700行左右。雖然小,但它實現了Web框架基本功能。這里就不以過多的筆墨去展示Bottle框架,需要的請訪問其網站了解更多。這里著重介紹與本文相關的重要對象request。在Bottle里,request對象代表了當前線程處理的請求,客戶端發送的請求數據如表單數據,請求網站和cookie都可以從request對象中獲得。下面是官方文檔中的兩個例子
from bottle import request, route, response, template

# 獲取客戶端cookie以實現登陸時問候用戶功能@route('/hello')def hello():  name = request.cookie.username or 'Guest'  return template('Hello {{name}}', name=name) # 獲取形如/forum?id=1&page=5的查詢字符串中id和page變量的值route('/forum')def display_forum():  forum_id = request.query.id  page = request.query.page or '1'  return template('Forum ID: {{id}} (page {{page}})', id=forum_id, page=page)

那么Bottle是如何實現的呢?根據WSGI接口規定,所有的HTTP請求信息都包含在一個名為envrion的dict對象中。所以Bottle要做的就是把HTTP請求信息從environ解析出來。在深入Request類如何實現之前先要了解下Bottle的FormsDict。FormsDict與字典類相似,但擴展了一些功能,比如支持屬性訪問、一對多的鍵值對、WTForms支持等。它在Bottle中被廣泛應用,如上面的示例中cookie和query數據都以FormsDict存儲,所以我們可以用request.query.page的方式獲取相應屬性值。

下面是0.12版Bottle中Request類的部分代碼,0.12版中Request類繼承了BaseRequest,為了方便閱讀我把代碼合并在一起,同時還有重要的DictProperty的代碼。需要說明的是Request類__init__傳入的environ參數就是WSGI協議中包含HTTP請求信息的envrion,而query方法中的_parse_qsl函數可以接受形如/forum?id=1&page=5原始查詢字符串然后以[(key1, value1), (ke2, value2), …]的list返回。

class DictProperty(object):  """ Property that maps to a key in a local dict-like attribute. """  def __init__(self, attr, key=None, read_only=False):    self.attr, self.key, self.read_only = attr, key, read_only  def __call__(self, func):    functools.update_wrapper(self, func, updated=[])    self.getter, self.key = func, self.key or func.__name__    return self  def __get__(self, obj, cls):    if obj is None: return self    key, storage = self.key, getattr(obj, self.attr)    if key not in storage: storage[key] = self.getter(obj)    return storage[key]  def __set__(self, obj, value):    if self.read_only: raise AttributeError("Read-Only property.")    getattr(obj, self.attr)[self.key] = value  def __delete__(self, obj):    if self.read_only: raise AttributeError("Read-Only property.")    del getattr(obj, self.attr)[self.key]class Request:  def __init__(self, environ=None):    self.environ {} if environ is None else envrion    self.envrion['bottle.request'] = self  @DictProperty('environ', 'bottle.request.query', read_only=True)  def query(self):    get = self.environ['bottle.get'] = FormsDict()    pairs = _parse_qsl(self.environ.get('QUERY_STRING', ''))    for key, value in pairs:      get[key] = value    return get            
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 辽阳市| 汤原县| 满城县| 平原县| 临安市| 浦北县| 吉木乃县| 磐安县| 武山县| 策勒县| 昆山市| 富源县| 葵青区| 眉山市| 崇明县| 汉阴县| 广平县| 金华市| 西平县| 静海县| 从江县| 阿克苏市| 宽城| 蓬溪县| 五台县| 仁怀市| 长汀县| 民勤县| 张家界市| 肇州县| 武义县| 正镶白旗| 平塘县| 汉中市| 洪洞县| 红河县| 沽源县| 清原| 鲁甸县| 隆昌县| 大冶市|