閱讀bottle.py源碼收獲


最近拿python的單文件開源web框架bottle源碼看了一下,麻雀雖小五臟俱全,看bottle源碼還是能學到很多python的實踐用法。

這里會陸續寫一些閱讀中的收獲。

 

1. makelist函數

def makelist(data):
'''包裝對象成為list'''
if isinstance(data, (tuple, list, set, dict)): return list(data)
elif data: return [data] # 對除去上述以外的元素生成list
else: return []

疑問:當碰到自定義的可迭代對象的時候,會返回[<iterator>]。在作者自己的代碼中沒有碰到這樣的情況,但是我們也可以來擴展一下。

def makelist_mod(data):
'''包裝任意對象成為list'''
if getattr(data, '__iter__', False): return list(data)
elif data: return [data]
else: return []

 

2. DictProperty裝飾器

class DictProperty(object):
'''映射修飾后的property到owner class中的某個類似字典的attribute
(后文也用property和attribute,而不用屬性,以表示區別)
'''
def __init__(self, attr, key=None, read_only=False):
self.attr, self.key, self.read_only = attr, key, read_only

# 以調用的方法使用裝飾器,則被裝飾的函數在__call__方法里作為參數傳入
def __call__(self, func):
# 用update_wrapper的方法把func的__module__,__name__,__doc__賦給裝飾后的attribute
functools.update_wrapper(self, func, updated=[])
self.getter, self.key = func, self.key or func.__name__
return self # 這個attribute是DictProperty的實例

def __get__(self, obj, cls): # 參數依次為被裝飾后的實例,owner class的實例,owner class
if obj is None: return self
key, storage = self.key, getattr(obj, self.attr) # self.attr是owner class的一個attribute
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 sample(object):
def __init__(self):
self.config = {}

@DictProperty('config', 'sample.foo', read_only=True)
def foo(self):
return 'foo'

@DictProperty('config', 'sample.bar', read_only=True)
def bar(self):
return 'bar'

歸納:這個裝飾器裝飾后形成的property在修改后,會改變owner class中綁定的attribute。

 

3. CachedProperty裝飾器

class CachedProperty(object):
'''每個實例只在第一次get的時候計算的property的值,之后存在instance的__dict__
中(當訪問對象的property時,如果__dict__中有,則先返回__dict__中記錄的值,如
果沒有,則執行被訪問property的__get__的方法。)
'''
def __init__(self, func):
self.func = func

def __get__(self, obj, cls):
if obj is None: return self
value = obj.__dict__[self.func.__name__] = self.func(obj)
return value

這個很簡單,能看懂上面DictProperty,這個小case了

 

4. lazy_attribute裝飾器

class lazy_attribute(object):
'''會在第一次調用的時候,把計算的結果設為owner class的attribute'''
def __init__(self, func):
functools.update_wrapper(self, func, updated=[])
self.getter = func

def __get__(self, obj, cls):
value = self.getter(cls)
setattr(cls, self.__name__, value)
return value

 

--------------------------------------------------------------------------------

 

 5. reloader實現

#coding: utf-8
import os, sys, time, subprocess, thread

# 當前文件路徑
path = os.path.abspath(__file__)

# 當前文件修改時間
mtime = os.stat(path).st_mtime

# 主進程為控制器,不做功能處理
if not os.environ.get('is_child'):
    argv = [sys.executable] + sys.argv
    environ = os.environ.copy()

    # 給子進程標記,不做控制功能
    environ['is_child'] = 'true'

    # 先開一個子進程,執行程序功能
    p = subprocess.Popen(argv, env=environ)

    while True:
        if os.stat(path).st_mtime != mtime:
            mtime = os.stat(path).st_mtime
            p = subprocess.Popen(argv, env=environ)
            print 'reloaded'

        time.sleep(1)


# 程序功能部分
def main():
    print 'try to modifdy this part and save!'
    raw_input() # 模擬監聽請求


# 新線程執行功能
thread.start_new_thread(main, ())

# 主線程監聽結束
while True:
    if mtime < os.stat(path).st_mtime:
        sys.exit(0)

    time.sleep(1)

 

 

未完待續......
















免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM