装饰器微妙之谈

简介: 装饰器微妙之谈


简单的装饰器


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。

相关文章
|
2天前
|
存储
面向对象技术(第二周)
面向对象技术(第二周)
|
12月前
|
Python
一日一技:你的代码是如何被炫技毁掉的
一日一技:你的代码是如何被炫技毁掉的
77 0
|
设计模式 算法 Java
当函数成为一等公民时,设计模式的变化
当函数成为一等公民时,设计模式的变化
当函数成为一等公民时,设计模式的变化
|
XML SQL 开发框架
C#十种语法糖
C#十种语法糖
118 0
C#十种语法糖
|
设计模式 缓存 Android开发
换个姿势,更好地参透EventBus(上)
EventBus(事件总线),跟之前写的 Handler 一样,老生常谈,教程早已烂大街
216 1
|
设计模式 存储 Java
换个姿势,更好地参透EventBus(中)
EventBus(事件总线),跟之前写的 Handler 一样,老生常谈,教程早已烂大街
90 0
|
安全 Java API
换个姿势,更好地参透EventBus(下)
EventBus(事件总线),跟之前写的 Handler 一样,老生常谈,教程早已烂大街
105 0
|
设计模式 算法 Java
巧妙的运用装饰器,让你的代码高出一个逼格!
又到了周末了,阿粉祝各位网友中秋快乐,阖家团圆!同时,节日期间,阿粉不打烊,欢迎网友观看吐槽~
巧妙的运用装饰器,让你的代码高出一个逼格!
|
人工智能 移动开发 自动驾驶
用大白话来聊聊:5G到底能干啥?
用大白话来聊聊:5G到底能干啥?
139 0
用大白话来聊聊:5G到底能干啥?