Python 装饰器

目录

函数
简单的装饰器

函数

理解装饰器前,你首先需要理解函数是如何工作的;

# 理解函数
>>> def add_one(number):
...     return number + 1

>>> add_one(2)
3

函数是一级对象(first-class objects),也就是说函数是可以作为参数来传递使用

# 函数是一级对象
def say_hello(name):
    return f"Hello {name}"

def be_awesome(name):
    return f"Yo {name}, together we are the awesomest!"

def greet_bob(greeter_func):
    return greeter_func("Bob")

# say_hello 这个函数作为参数被使用
>>> greet_bob(say_hello)    # greet_bob() 与 say_hello 的区别是一个带括号,一个没有括号;其中say_hello函数只有传递的作用,而greet_bob()函数是调用执行。
'Hello Bob'
# be_awesome这个函数作为参数被使用
>>> greet_bob(be_awesome)
'Yo Bob, together we are the awesomest!'

内嵌函数(inner function)就是在其他函数中定义函数,例如:

def parent():
    print("Printing from the parent() function")

    def first_child():
        print("Printing from the first_child() function")

    def second_child():
        print("Printing from the second_child() function")

    second_child()
    first_child()
# 调用parent()函数
>>> parent()
Printing from the parent() function
Printing from the second_child() function
Printing from the first_child() function

从函数中返回函数

用函数作为返回值,例如:

def parent(num):
    def first_child():
        return "Hi, I am Emma"

    def second_child():
        return "Call me Liam"

    if num == 1:
        return first_child
    else:
        return second_child

注意返回的 first_child 不带括号,就是直接返回引用的函数 first_child;相反first_child()是对函数求值的结果。

# 接上
>>> first = parent(1)
>>> second = parent(2)

>>> first
<function parent.<locals>.first_child at 0x7f599f1e2e18>

>>> second
<function parent.<locals>.second_child at 0x7f599dad5268>

>>> first()
'Hi, I am Emma'

>>> second()
'Call me Liam'

简单的装饰器

装饰器,其本身接收一个函数对象作为参数,然后做一些工作后,返回接收的参数,供外界调用。
简而言之:装饰器包装一个函数,改变其行为。

# 装饰器

def my_decorator(func):
    def wrapper():
        print("Something is happening before the function is called.")
        func()
        print("Something is happening after the function is called.")
    return wrapper

def say_whee():
    print("Whee!")

say_whee = my_decorator(say_whee)


# 调用say_whee()
>>> say_whee()
Something is happening before the function is called.
Whee!
Something is happening after the function is called.

为了不打扰邻居休息,下面的例子只在白天运行经过修饰的代码。
如果你试着在夜间调用say_whee(),什么也不会发生。

from datetime import datetime

def not_during_the_night(func):
    def wrapper():
        if 7 <= datetime.now().hour < 22:
            func()
        else:
            pass  # Hush, the neighbors are asleep
    return wrapper

def say_whee():
    print("Whee!")

say_whee = not_during_the_night(say_whee)

语法糖
用say_whee()的方式来修饰显得有点笨拙,而且装饰在定义函数下面隐藏了一些。

def my_decorator(func):
    def wrapper():
        print("Something is happening before the function is called.")
        func()
        print("Something is happening after the function is called.")
    return wrapper

@my_decorator
def say_whee():
    print("Whee!")

@my_decorator 是一种更简单的写法 代替say_whee = my_decorator(say_whee)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。