python 裝飾器 二

1. 將單方法的類轉換爲函數

你有一個除 __init__() 方法外只定義了一個方法的類。爲了簡化代碼,你想將它轉換成一個函數。閉包

from urllib.request import urlopen

class UrlTemplate:
    def __init__(self, template):
        self.template = template

    def open(self, **kwargs):
        return urlopen(self.template.format_map(kwargs))

# Example use. Download stock data from yahoo
yahoo = UrlTemplate('http://finance.yahoo.com/d/quotes.csv?s={names}&f={fields}')
for line in yahoo.open(names='IBM,AAPL,FB', fields='sl1c1v'):
    print(line.decode('utf-8'))

能夠替換爲:app

def urltemplate(template):
    def opener(**kwargs):
        return urlopen(template.format_map(kwargs))
    return opener

# Example use
yahoo = urltemplate('http://finance.yahoo.com/d/quotes.csv?s={names}&f={fields}')
for line in yahoo(names='IBM,AAPL,FB', fields='sl1c1v'):
    print(line.decode('utf-8'))

任什麼時候候只要你碰到須要給某個函數增長額外的狀態信息的問題,均可以考慮使用閉包。 相比將你的函數轉換成一個類而言,閉包一般是一種更加簡潔和優雅的方案。函數

2. 定義一個帶參數的裝飾器

假設你想寫一個裝飾器,給函數添加日誌功能,當時容許用戶指定日誌的級別和其餘的選項。 下面是這個裝飾器的定義和使用示例:url

from functools import wraps
import logging

def logged(level, name=None, message=None):
    """
    Add logging to a function. level is the logging
    level, name is the logger name, and message is the
    log message. If name and message aren't specified,
    they default to the function's module and name.
    """
    def decorate(func):
        logname = name if name else func.__module__
        log = logging.getLogger(logname)
        logmsg = message if message else func.__name__

        @wraps(func)
        def wrapper(*args, **kwargs):
            log.log(level, logmsg)
            return func(*args, **kwargs)
        return wrapper
    return decorate

# Example use
@logged(logging.DEBUG)
def add(x, y):
    return x + y
def add(x, y):
    return x + y
    
add = logged(logging.DEBUG)(add)

logged() 接受參數並返回一個可調用對象,可調用對象接受一個函數做爲參數幷包裝它.日誌

相關文章
相關標籤/搜索