Fluent Python

函数装饰器与闭包

2017-12-30  本文已影响24人  一块大番薯

装饰器基础知识

装饰器通常会定义一个内部函数,然后将它返回,而使用内部函数的代码要靠闭包才能正确运行,为了理解闭包又得先理解变量作用域

变量作用域规则

UnboundLocalError

闭包

指延伸了作用域的函数


菜鸟的做法
较好的做法
nonlocal 声明
UnboundLocalError
实现一个简单的装饰器
装饰器
内部函数
不足之处:
(1)不支持关键字参数
(2)屏蔽了被装饰函数的 _name_ 和 _doc_ 属性
functools.wraps 装饰器可以把相关属性从 func 复制到 clocked,且能正确处理关键字参数
只需对内部函数 clocked 使用 @functools.wraps(func) 即可

标准库中的装饰器

functools.lru_cache
实现备忘(memoization)功能,把耗时的函数结果保存起来,避免重复计算
lru 是 Least Recently Used 缩写,表明缓存不会无限制增长,一段时间后不用的缓存会被丢弃。

lru_cache
lru_cache() 括号内接受配置 :

functools.singledispatch

from functools import singledispatch
from collections import abc
import numbers
import html

@singledispatch
def htmlize(obj):
    content = html.escape(repr(obj))
    return '<pre>{}</pre>'.format(content)
    
@htmlize.register(str)
def _(text):
    print('传入的第一个参数是 str')
    
@htmlize.register(tuple)
@htmlize.register(abc.MutableSequence)
def _(seq):
        print('传入的第一个参数是 tuple 或 list')
单分派泛函数

参数化装饰器

指接受参数的装饰器。
创建一个装饰器工厂函数,把参数传给它,返回一个装饰器,最后把这个装饰器应用到被装饰的函数

registy = set()

def regitster(active=True):
    def decorate(func):
        print('running regitster active(%s), decorate(%s)' % (active, func))
        if active:
            registy.add(func)
        else:
            registy.discard(func)
        return func
    return decorate
    
@regitster()
def f1():
    print('running f1()')
    
@regitster(active=False)
def f2():
    print('running f2()')
上一篇下一篇

猜你喜欢

热点阅读