sugar/ 九月 2, 2019/ python设计模式/ 0 comments

修饰器(Decorator)模式能够以透明的方式(不会影响其他对象)动态地将功能添加到一个对象中

一个Python修饰器就是对Python语法的一个特定改变,用于扩展一个类、方法或函数的行为,而无需使用继承。从实现的角度来说,Python修饰器是一个可调用对象(函数、方法、类),接受一个函数对象fin作为输入,并返回另一个函数对象 fout。这意味着可以将任何具有这些属性的可调用对象当作一个修饰器。

修饰器模式和Python修饰器之间并不是一对一的等价关系。Python修饰器能做的实际上比修饰器模式多得多,其中之一就是实现修饰器模式。

下图展示了我们可以如何使用一些专用配件来修饰一把枪,使其无声、更准以及更具破坏力。

实现一个memoization修饰器:

# coding: utf-8

import functools


def memoize(fn):
    known = dict()

    @functools.wraps(fn)
    def memoizer(*args):
        if args not in known:
            known[args] = fn(*args)
        return known[args]

    return memoizer


@memoize
def nsum(n):
    '''返回前n个数字的和'''
    assert(n >= 0), 'n must be >= 0'
    return 0 if n == 0 else n + nsum(n-1)


@memoize
def fibonacci(n):
    '''返回斐波那契数列的第n个数'''
    assert(n >= 0), 'n must be >= 0'
    return n if n in (0, 1) else fibonacci(n-1) + fibonacci(n-2)

if __name__ == '__main__':
    from timeit import Timer
    measure = [{'exec': 'fibonacci(100)', 'import': 'fibonacci',
                'func': fibonacci}, {'exec': 'nsum(200)', 'import': 'nsum',
                                     'func': nsum}]
    for m in measure:
        t = Timer('{}'.format(m['exec']), 'from __main__ import \
            {}'.format(m['import']))
        print('name: {}, doc: {}, executing: {}, time: \
            {}'.format(m['func'].__name__, m['func'].__doc__,
                       m['exec'], t.timeit()))

使用修饰器进行一层额外的封装,基于某个条件来决定是否执行真正的修饰器。

修饰器的另一个有趣的特性是可以使用多个修饰器来修饰一个函数。

使用修饰器模式来扩展一个对象的行为,无需使用继承,非常方便。Python进一步扩展了修饰器的概念,允许我们无需使用继承或组合就能扩展任意可调用对象(函数、方法或类)的行为。我们可以使用Python内置的修饰器特性。

修饰器模式是实现横切关注点的绝佳方案,因为横切关注点通用但不太适合使用面向对象编程范式来实现。

Share this Post

说点什么

avatar
  Subscribe  
提醒