前端开发那些事儿

python设计模式5装饰器

2021-07-08  本文已影响0人  python测试开发

第二个值得学习的结构模式是装饰器模式,它允许程序员以透明的方式(影响其他对象)动态地给对象增加能力。

可以用Pythonic的方式来写装饰器(意味着使用语言的特性),这要归功于内置的装饰器特性(https://docs.python.org/3/reference/compound_stmts.html#function)。

Python 装饰器是一个可调用的(函数、方法或类),它获得一个函数对象 func_in 作为输入,并返回另一个函数对象 func_out。它用于扩展函数、方法或类的行为。

真实世界的例子

装饰器模式通常用于扩展对象的功能。在日常生活中,这种扩展的例子有:在枪上加一个消音器,使用不同的相机镜头等等。

Django框架中有大量装饰器

Pyramid框架和Zope应用服务器也使用装饰器来实现各种目标。

应用

装饰器模式在跨领域方面大放异彩:

使用修饰器模式的另一个常见例子是(Graphical User Interface,GUI)工具集。在GUI工具集中,我们希望能够将一些特性,比如边框、阴影、颜色以及滚屏,添加到组件/控件。

实例

所有的递归函数都可以从缓存中受益,所以让我们尝试返回前n个数字之和的函数number_sum()。

def number_sum(n): 
    '''Returns the sum of the first n numbers''' 
    assert(n >= 0), 'n must be >= 0' 
    
    if n == 0:
        return 0
    else:
        return n + number_sum(n-1)  
 
if __name__ == '__main__': 
    from timeit import Timer 
    t = Timer('number_sum(30)', 'from __main__ import number_sum')
    print('Time: ', t.timeit())

执行输出耗时:Time: 34.952999532999456

下面的代码中,我们使用dict来缓存已经计算好的和。我们还改变了传递给number_sum()函数的参数。我们想计算前300个数字的和,而不是只计算前30个。

sum_cache = {0:0}
  
def number_sum(n): 
    '''Returns the sum of the first n numbers''' 
    assert(n >= 0), 'n must be >= 0'
    
    if n in sum_cache:
        return sum_cache[n]
    res = n + number_sum(n-1)
    # Add the value to the cache
    sum_cache[n] = res
    return res
         
if __name__ == '__main__': 
    from timeit import Timer 
    t = Timer('number_sum(300)', 'from __main__ import number_sum')
    print('Time: ', t.timeit())

执行输出耗时:Time: 1.2133596080002462。快了但是单码复杂了,且不方便复用。改用lru_cache装饰器会更清晰:

from functools import lru_cache

@lru_cache
def number_sum(n): 
    '''Returns the sum of the first n numbers''' 
    assert(n >= 0), 'n must be >= 0' 
    
    if n == 0:
        return 0
    else:
        return n + number_sum(n-1)  
 
if __name__ == '__main__': 
    from timeit import Timer 
    t = Timer('number_sum(30)', 'from __main__ import number_sum')
    print('Time: ', t.timeit())
上一篇下一篇

猜你喜欢

热点阅读