Python深入05 装饰器

简介: 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明。谢谢!   装饰器(decorator)是一种高级Python语法。装饰器可以对一个函数、方法或者类进行加工。

作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明。谢谢!

 

装饰器(decorator)是一种高级Python语法。装饰器可以对一个函数、方法或者类进行加工。在Python中,我们有多种方法对函数和类进行加工,比如在Python闭包中,我们见到函数对象作为某一个函数的返回结果。相对于其它方式,装饰器语法简单,代码可读性高。因此,装饰器在Python项目中有广泛的应用。

装饰器最早在Python 2.5中出现,它最初被用于加工函数和方法这样的可调用对象(callable object,这样的对象定义有__call__方法)。在Python 2.6以及之后的Python版本中,装饰器被进一步用于加工类。

 

装饰函数和方法

我们先定义两个简单的数学函数,一个用来计算平方和,一个用来计算平方差:

# get square sum
def square_sum(a, b):
    return a**2 + b**2

# get square diff
def square_diff(a, b):
    return a**2 - b**2

print(square_sum(3, 4))
print(square_diff(3, 4))

在拥有了基本的数学功能之后,我们可能想为函数增加其它的功能,比如打印输入。我们可以改写函数来实现这一点:

# modify: print input

# get square sum
def square_sum(a, b):
    print("intput:", a, b)
    return a**2 + b**2

# get square diff
def square_diff(a, b):
    print("input", a, b)
    return a**2 - b**2

print(square_sum(3, 4))
print(square_diff(3, 4))

我们修改了函数的定义,为函数增加了功能。

 

现在,我们使用装饰器来实现上述修改:

def decorator(F):
    def new_F(a, b):
        print("input", a, b)
        return F(a, b)
    return new_F

# get square sum
@decorator
def square_sum(a, b):
    return a**2 + b**2

# get square diff
@decorator
def square_diff(a, b):
    return a**2 - b**2

print(square_sum(3, 4))
print(square_diff(3, 4))

装饰器可以用def的形式定义,如上面代码中的decorator。装饰器接收一个可调用对象作为输入参数,并返回一个新的可调用对象。装饰器新建了一个可调用对象,也就是上面的new_F。new_F中,我们增加了打印的功能,并通过调用F(a, b)来实现原有函数的功能。

定义好装饰器后,我们就可以通过@语法使用了。在函数square_sum和square_diff定义之前调用@decorator,我们实际上将square_sum或square_diff传递给decorator,并将decorator返回的新的可调用对象赋给原来的函数名(square_sum或square_diff)。 所以,当我们调用square_sum(3, 4)的时候,就相当于:

square_sum = decorator(square_sum)
square_sum(3, 4)

我们知道,Python中的变量名和对象是分离的。变量名可以指向任意一个对象。从本质上,装饰器起到的就是这样一个重新指向变量名的作用(name binding),让同一个变量名指向一个新返回的可调用对象,从而达到修改可调用对象的目的。

与加工函数类似,我们可以使用装饰器加工类的方法。

 

如果我们有其他的类似函数,我们可以继续调用decorator来修饰函数,而不用重复修改函数或者增加新的封装。这样,我们就提高了程序的可重复利用性,并增加了程序的可读性。

 

含参的装饰器

在上面的装饰器调用中,比如@decorator,该装饰器默认它后面的函数是唯一的参数。装饰器的语法允许我们调用decorator时,提供其它参数,比如@decorator(a)。这样,就为装饰器的编写和使用提供了更大的灵活性。

# a new wrapper layer
def pre_str(pre=''):
    # old decorator
    def decorator(F):
        def new_F(a, b):
            print(pre + "input", a, b)
            return F(a, b)
        return new_F
    return decorator

# get square sum
@pre_str('^_^')
def square_sum(a, b):
    return a**2 + b**2

# get square diff
@pre_str('T_T')
def square_diff(a, b):
    return a**2 - b**2

print(square_sum(3, 4))
print(square_diff(3, 4))

上面的pre_str是允许参数的装饰器。它实际上是对原有装饰器的一个函数封装,并返回一个装饰器。我们可以将它理解为一个含有环境参量的闭包。当我们使用@pre_str('^_^')调用的时候,Python能够发现这一层的封装,并把参数传递到装饰器的环境中。该调用相当于:

square_sum = pre_str('^_^') (square_sum)

 

装饰类

在上面的例子中,装饰器接收一个函数,并返回一个函数,从而起到加工函数的效果。在Python 2.6以后,装饰器被拓展到类。一个装饰器可以接收一个类,并返回一个类,从而起到加工类的效果。

def decorator(aClass):
    class newClass:
        def __init__(self, age):
            self.total_display   = 0
            self.wrapped         = aClass(age)
        def display(self):
            self.total_display += 1
            print("total display", self.total_display)
            self.wrapped.display()
    return newClass

@decorator
class Bird:
    def __init__(self, age):
        self.age = age
    def display(self):
        print("My age is",self.age)

eagleLord = Bird(5)
for i in range(3):
    eagleLord.display()

在decorator中,我们返回了一个新类newClass。在新类中,我们记录了原来类生成的对象(self.wrapped),并附加了新的属性total_display,用于记录调用display的次数。我们也同时更改了display方法。

通过修改,我们的Bird类可以显示调用display的次数了。

 

总结

装饰器的核心作用是name binding。这种语法是Python多编程范式的又一个体现。大部分Python用户都不怎么需要定义装饰器,但有可能会使用装饰器。鉴于装饰器在Python项目中的广泛使用,了解这一语法是非常有益的。

 

欢迎继续阅读“Python快速教程

 

目录
相关文章
|
4天前
|
设计模式 开发框架 缓存
探索Python中的装饰器:简化代码,增强功能
【9月更文挑战第16天】在Python的世界里,装饰器宛如一位巧手魔术师,轻轻一挥魔杖,便能让我们的函数和类焕发新生。本文将带你领略装饰器的魔力,从基础概念到实战应用,一步步解锁装饰器的强大潜能。让我们一起踏上这段奇妙的旅程,探索如何用装饰器简化代码,增强功能。
|
5天前
|
API Python
探索Python中的装饰器
【9月更文挑战第15天】本文将带你深入了解Python装饰器的概念、用法和实现,让你对这一强大而灵活的工具有更全面的认识。我们将从基础概念出发,逐步深入到高级应用,通过实例代码演示如何利用装饰器优化代码结构、增强函数功能以及管理API版本。
31 15
|
5天前
|
Python
探索Python中的装饰器:从基础到进阶
【9月更文挑战第15天】本文旨在通过深入浅出的方式介绍Python中装饰器的概念、用法及其背后的原理。我们将从装饰器的简单定义开始,逐步深入到如何自定义装饰器,并探讨其在不同场景下的应用。文章不仅包含理论知识,还提供了实际代码示例,帮助读者更好地理解和掌握这一强大的工具。
|
4天前
|
缓存 开发者 Python
探索Python中的装饰器:从基础到高级应用
本文旨在深入探讨Python中一个强大且灵活的特性——装饰器(Decorator)。通过图文并茂的方式,我们将从装饰器的基本概念入手,逐步揭示其背后的工作原理,并通过一系列实用示例展示如何在实际编程中有效利用装饰器来增强代码的可读性、可维护性和功能性。最终,我们希望读者不仅能掌握装饰器的基础用法,还能激发创新思维,探索出更多高级应用场景。
18 9
|
4天前
|
开发框架 缓存 数据库
探索Python中的装饰器:从入门到实践
【8月更文挑战第48天】本文将引导你进入Python装饰器的奇妙世界。不同于传统的“摘要”格式,我们将通过一段代码的演变,直观展示装饰器的魅力。文章不仅介绍基础概念,还将通过实例演示如何自定义装饰器,并探讨其在实际应用中的强大用途。让我们开始吧,一起深入理解这个改变函数行为的强大工具!
|
1天前
|
设计模式 监控 数据安全/隐私保护
探索Python中的装饰器:从基础到高级应用
Python的装饰器是一种强大而灵活的工具,它允许开发者在不修改现有函数代码的情况下,增加或修改函数的行为。本文将深入探讨装饰器的基本概念、实际应用以及如何利用装饰器编写更加高效和可维护的代码。通过具体的代码示例,我们将揭示装饰器在软件开发中的巨大潜力。
|
1天前
|
缓存 Python
探索Python中的装饰器:原理与应用
本文深入探讨了Python中装饰器的概念,从基本定义到实际应用进行了系统性的阐述。通过实例展示了如何利用装饰器来增强函数功能,同时详细解释了其背后的运行机制和实现原理。此外,文章还讨论了装饰器在软件开发中的实际应用场景,为读者提供了实用的编程技巧和最佳实践。
|
3天前
|
缓存 开发者 Python
探索Python中的装饰器
本文将深入探讨Python中一个高级且强大的功能——装饰器。我们将从基本概念开始,逐步解析其工作原理及实际应用。通过具体示例,读者将能够理解如何使用装饰器来扩展函数功能,以及如何利用这一特性优化代码结构。无论是新手还是经验丰富的开发者,都能从中获取有价值的见解。
15 5
|
2天前
|
Python
探索Python编程中的装饰器
【9月更文挑战第18天】本文将深入探讨Python中的一项强大功能——装饰器。通过简化的实例,我们会了解如何创建和使用装饰器来增强函数的功能,同时保持代码的整洁性和可读性。
10 3
|
4天前
|
测试技术 Python
Python中的装饰器:简化代码的魔法
【9月更文挑战第16天】在Python编程的世界里,装饰器就像是一把瑞士军刀,它们为函数和类赋予了额外的超能力。本文将带你探索装饰器的秘密,了解如何利用这一工具来简化代码、增强可读性并提升效率。从基础概念到实际案例,我们将一步步揭示装饰器的神秘面纱,让你的代码更加优雅和强大。