你有一个除 __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'))
任什么时候候只要你碰到须要给某个函数增长额外的状态信息的问题,均可以考虑使用闭包。 相比将你的函数转换成一个类而言,闭包一般是一种更加简洁和优雅的方案。函数
假设你想写一个装饰器,给函数添加日志功能,当时容许用户指定日志的级别和其余的选项。 下面是这个装饰器的定义和使用示例: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()
接受参数并返回一个可调用对象,可调用对象接受一个函数做为参数并包装它.日志