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() 接受参数并返回一个可调用对象,可调用对象接受一个函数做为参数并包装它.日志

相关文章
相关标签/搜索