装饰器微妙之谈

简介: 装饰器微妙之谈


简单的装饰器


def my_decorate(fun):
    def wrapper():
        print('这是个装饰器!')
        func()
     reture wapper
def greet():
 print('hello world')
greet = my_decorator(greet)
greet()
# 输出
这是个装饰器!
hello world

这段代码中变量 greet 指向了内部函数 wrapper(),而内部函数 wrapper() 中又会调用原函数 greet(),因此,最后调用 greet() 时,就会先打印 'wrapper of decorator',然后输出'hello world'。大家应该都明白!


这里的函数 my_decorator() 就是一个装饰器,它把真正需 要执行的函数 greet() 包裹在其中,并且改变了它的行为, 但是原函数 greet() 不变。


我们换一种写法,使用Python来装饰它

def my_decorator(func):   
    def wrapper():    
       print('wrapper of decorator')   
        func()  
    return wrapper
@my_decorator
def greet(): 
   print('hello world')
greet()

这里的@,我们称之为语法糖,@my_decorator就相当于 前面的greet=my_decorator(greet)语句,只不过更加 简洁。因此,如果你的程序中有其它函数需要做类似的装饰,你只需在它们的上方加上@decorator就可以了,这样 就大大提高了函数的重复利用和程序的可读性。


带有参数的装饰器


如果原函数 greet() 中,有参数需要传递给 装饰器怎么办?一个简单的办法,是可以在对应的装饰器函数 wrapper() 上,加上相应的参数,比如:


def my_decorator(func):
    def wrapper(message):
       print('wrapper of decorator')
       func(message)
     return wrapper
@my_decorator
def greet(message):
     print(message)
greet('hello world')
# 输出
wrapper of decorator
hello world


事实上,通常情况下,我们会把*args和**kwargs,作为 装饰器内部函数 wrapper() 的参数。


def my_decorator(func):
    def wrapper(*args, **kwargs):
       print('wrapper of decorator')
       func(*args, **kwargs)
    return wrapper

类装饰器


实际上,类也可 以作为装饰器。类装饰器主要依赖于函数__call_(),每当你调用一个类的示例时,函数__call__() 就会被执行一 次

class Count:
   def __init__(self, func):
       self.func = func
       self.num_calls = 0
   def __call__(self, *args, **kwargs):
       self.num_calls += 1
       print('num of calls is: {}'.format(self.num_calls))
       return self.func(*args, **kwargs)
@Count
def example():
   print("hello world")
example()
# 输出
num of calls is: 1
hello world
example()
# 输出
num of calls is: 2
hello world

这里,定义了类 Count,初始化时传入原函数 func(), 而__call__() 函数表示让变量 num_calls 自增 1,然后打印,并且调用原函数。因此,在我们第一次调用函数 example() 时,num_calls 的值是 1,而在第二次调用时, 它的值变成了 2。

相关文章
|
3月前
|
Java 程序员
让我们一起探讨Java多态的奥秘,看看它是如何打破“一刀切”的局限,让我们的代码更加生动多彩
让我们一起探讨Java多态的奥秘,看看它是如何打破“一刀切”的局限,让我们的代码更加生动多彩
42 5
|
1月前
|
安全 程序员 编译器
【C++篇】继承之韵:解构编程奥义,领略面向对象的至高法则
【C++篇】继承之韵:解构编程奥义,领略面向对象的至高法则
81 11
|
4月前
|
Python
告别平庸!Python元类:让你的代码设计思想跃升至新高度
【7月更文挑战第7天】Python的元类是创建类的类,用于在定义时定制类的行为。通过元类,可以在类创建时注入逻辑,比如添加方法或改变属性。例如,一个元类可以自动为所有类添加日志功能。元类应用广泛,如自动注册类、修改属性、实现单例模式和动态添加方法,提升代码设计的灵活性和效率。掌握元类,让代码设计超越常规。
30 1
|
4月前
|
算法
代码之美:从混乱到秩序的编程之旅
【7月更文挑战第14天】编程,一门将思维转化为电子指令的艺术。在这篇文章中,我将带你领略编程的美学,从最初的混沌编码到最终的逻辑严谨、运行高效的程序。我们将一同探索如何通过理解问题、选择合适的数据结构与算法、编写可读性强的代码以及不断重构来提升代码质量。这不仅是一个技术提升的过程,更是一次思维的升华。
|
4月前
|
设计模式 开发者 Python
惊呆了!Python元类竟能如此玩转,你的编程世界将不再有界限
【7月更文挑战第6天】Python元类是类的类,用于控制类的创建。它们让开发者能自定义类的行为,如添加方法、改变继承或实例化过程。例如,定义一个元类`my_metaclass`,它会在创建类时自动添加新方法。元类广泛应用在单例、插件系统和ORM等高级场景,拓展了Python代码的灵活性和威力。掌握元类,揭开编程魔法的面纱,为代码解锁更多可能。
25 0
|
6月前
|
设计模式
代码之美:简洁性与可读性的和谐共舞
【5月更文挑战第18天】 在软件工程的世界中,"简洁"和"可读性"这两个词经常被提起,但它们之间的平衡却像一场优雅的舞蹈,需要精心编排每一个步骤。本文将探讨如何在编写技术代码时实现这种平衡,以及这一平衡对于提高代码效率、降低维护成本及促进团队合作的重要性。通过实例分析和个人经验分享,我们将深入理解简洁与可读性如何相辅相成,共同构建更加健壮、高效且易于维护的代码基石。
50 4
|
6月前
|
存储
面向对象技术(第二周)
面向对象技术(第二周)
|
6月前
|
程序员 开发者
代码与禅意:寻找编程中的内在和谐
【4月更文挑战第8天】 在数字世界的纷繁复杂中,编程不仅仅是一项技能,更是一种艺术。本文探讨了编程与禅宗哲学之间的深层联系,阐述了如何在技术的冰冷逻辑中寻找到心灵的温暖和内在的和谐。通过反思编程过程中的创造力、专注力和简洁性,我们能够揭示出技术实践与精神修养之间的桥梁。
|
6月前
|
算法
犯错总结--工厂模式和策略模式傻傻没分清
犯错总结--工厂模式和策略模式傻傻没分清
60 0
犯错总结--工厂模式和策略模式傻傻没分清
|
存储 Java
i++和++i傻傻分不清楚?这里给你最清楚的解答
i++和++i傻傻分不清楚?这里给你最清楚的解答
i++和++i傻傻分不清楚?这里给你最清楚的解答