Python装饰器扫盲

函数的嵌套

def func(message):
    def getMessage(message):
        print("got a message {}".format(message))
    return getMessage(message)



if __name__ == "__main__":
    func("我是海贼王")

函数返回值是函数(闭包)

def func2():
    def printMessage(message):
        print("got a message {}".format(message))
    return printMessage

if __name__ == "__main__":
    func("我是海贼王")

    send_message = func2()
    send_message("我也是海贼王")

简单的装饰器

def my_decorator(func):
    def wrapper():
        print("wrapper of decorator")
        func()
    return wrapper


def my_greet():
    print("hello 我是海贼王路飞")

if __name__ == "__main__":
    func("我是海贼王")

    send_message = func2()
    send_message("我也是海贼王")

    decorate = my_decorator(my_greet)

    decorate()

my_greet 函数 被 my_decorator 函数 增强了,本来my_greet 函数只会输出 “hello 我是海贼王路飞”,经过my_decorator 的增强后,多了一句 wrapper of decorator

利用Python的特性简化上面的调用流程

def my_decorator(func):
    def wrapper():
        print("wrapper of decorator")
        func()
    return wrapper


@my_decorator
def my_greet():
    print("hello 我是海贼王路飞")
    
my_greet()

这里的@,我们称之为语法糖,@my_decorator就相当于前面的greet=my_decorator(greet)语句,只不过更加简洁

带参数的装饰器

 # 带参数的装饰器
def withArgsDecorator(func):
    def wrapper(message):
        print("with args of decorator")
        func(message)
    return wrapper

@withArgsDecorator
def greetWithName(name):
    print("我是 {}".format(name))

多个参数的装饰器

事实上,通常情况下,我们会把*args和kwargs,作为装饰器内部函数 wrapper() 的参数。*args和kwargs,表示接受任意数量和类型的参数,因此装饰器就可以写成下面的形式:

 # 带多个不定参数的装饰器
def withArgsDecorator(func):
    def wrapper(*args,**kwargs):
        print("with args of decorator")
        func(*args,**kwargs)
    return wrapper

@withArgsDecorator
def greetWithName(name):
    print("我是 {}".format(name))

类装饰器

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

## 定义一个类装饰器
def my_class_decorator(cls):
   # 在类被实例化之前执行一些操作
   cls.some_attribute = "Added by the decorator"
   return cls  # 返回修改后的类

## 使用类装饰器来装饰一个类
@my_class_decorator
class MyClass:
   def __init__(self, value):
       self.value = value

## 创建类的实例
obj = MyClass(42)

## 访问被类装饰器修改后的属性
print(obj.some_attribute)  ## 输出 "Added by the decorator"
在上面的示例中,my_class_decorator 是一个类装饰器,它接受一个类作为参数,并可以修改该类,然后返回修改后的类。当你用 @my_class_decorator 装饰 MyClass 类时,MyClass 类被传递给 my_class_decorator,它在其中添加了一个新的属性 some_attribute。然后,你可以在类的实例中访问这个属性。

类装饰器可以用于各种用途,包括添加属性、方法、修改类的行为等。你可以根据需要编写自定义的类装饰器,以满足你的项目需求。

装饰器用法实例

装饰器在用户登录验证中的一个常见用法是,它可以用来检查用户是否已登录,以确保只有已登录的用户才能访问某些受保护的页面或执行某些操作。以下是一个示例,演示如何使用装饰器实现用户登录验证:

pythonCopy code# 模拟用户登录状态
is_user_logged_in = False

# 定义用户登录验证装饰器
def login_required(func):
    def wrapper(*args, **kwargs):
        if is_user_logged_in:
            return func(*args, **kwargs)
        else:
            return "请先登录"
    return wrapper

# 使用装饰器来保护需要登录的功能
@login_required
def protected_function():
    return "这是一个受保护的功能,只有已登录用户才能访问"

# 模拟用户登录
is_user_logged_in = True

# 调用受保护的功能
result = protected_function()
print(result)  # 输出 "这是一个受保护的功能,只有已登录用户才能访问"

# 模拟用户未登录
is_user_logged_in = False

# 再次调用受保护的功能
result = protected_function()
print(result)  # 输出 "请先登录"

在上述示例中,login_required 是一个装饰器,它检查用户是否已登录。如果用户已登录,则执行原始的函数(这里是protected_function),否则返回一个提示信息。通过在需要登录验证的功能上使用@login_required 装饰器,你可以确保只有已登录用户才能访问这些功能。

在实际应用中,用户登录状态通常会与会话管理或身份验证系统相关联,而不是简单地使用一个布尔标志来表示。但是,这个示例演示了如何使用装饰器来实现用户登录验证的基本概念。你可以根据实际需求扩展这个概念,并与实际的用户身份验证机制集成。

你可能感兴趣的:(人生苦短来玩Python,1024程序员节)