python学习笔记四——把函数当作对象

4.把函数当作对象

4.1闭包

#计算移动平均值
def make_averager():
    count = 0
    total = 0
    
    def averager(new_value):
        nonlocal count, total
        count += 1
        total += new_value
        return total / count 
    return averager
#test
ave = make_averager()
ave(10)
ave(20)

4.2装饰器

#一个简单的装饰器,支持处理关键字参数
import time
​
DEFAULT_FMT = '[{elasped:0.8f}s] {name} {name}({args}) -> {result}'
​
def clock(fmt=DEFAULT_FMT):
    def decorate(func):
        def clocked(*_args):
            t0 = time.time()
            _result = func(*_args)
            elasped = time.time() - t0
            name = func.__name__
            args = ', '.join(repr(arg) for arg in _args)
            result = repr(_result)
            print(fmt.format(**locals()))
            return _result
        return clocked
    return decorate
​
@clock()
def snooze(seconds):
    time.sleep(seconds)
​
for i in range(3):
   snooze(.123)

4.3单分派泛函数

#functools.singledspatch装饰器可以把整体方案拆分为多个模块,使用@singledspatch装饰的普通函数会变为泛函数:根据第一个参数的类型,以不同的方式执行相同的操作的一组函数
from functools import singledspatch
from collections import abc
from numbers
from html
​
@singledspatch
def htmlize(obj):
    content = html.escape(repr(obj))
    return '<pre>{}</pre>'.format(content)
​
@htmlize.register(str)
def _(text):
    content = html.escape(text).replace('\n', '<br>\n')
    return '<p>{0}</p>'.format(content)
​
@htmlize.register(numbers.Integral)
def _(n):
    return '<pre>{0} (0x{0:x})</pre>'.format(n)
​
@htmlize.register(tuple)
@htmlize.register(abc.MutableSequence)
def _(seq):
    inner = '</li>\n<li>'.join(htmlize(item) for item in seq)
    return '<ul>\n<li>' + inner + '</li>\n</ul>

4.4参数化装饰器

#为了便于启用或禁用register执行的函数注册功能,我们为它提供了一个可选的active参数,设为False时,不注册被装饰的函数
registry = set()
def register(active=False):
    def decorator(func):
        print('running register(active=%s) -> decorator(%s)'
             % (active,func))
        if active:
            registry.add(func)
        else:
            registry.discard(func)
        return func
    return decorator
​
@register(active=False)
def f1():
    print('running f1')
   
@register(active=True)
def f2(active=True):
    print('running f2')
    
def f3():
    print('runing f3')
​
#test
registry
#为了接受新参数,新的register装饰器必须作为函数调用
register(active=True)(f3)
registry
    
register(active=False)(f2)
registry

猜你喜欢

转载自blog.csdn.net/jasonzhoujx/article/details/81506261