Easton's Blog Easton's Blog
首页
  • 编程语言

    • Python
  • 框架

    • Django
  • Mdn (opens new window)
  • HTML
  • CSS
  • JavaScript
  • Mysql
  • PostgreSQL
  • Elasticsearch
  • MongoDB
  • Redis
  • 服务器命令
  • Docker
  • GIT
  • 摄影
  • 草稿
  • 归类方式

    • 分类
    • 标签
    • 归档
  • 关于博客

    • 博客教程
    • 友情链接
    • 关于
导航站
GitHub (opens new window)

Easton Yang

爱生活😊爱学习
首页
  • 编程语言

    • Python
  • 框架

    • Django
  • Mdn (opens new window)
  • HTML
  • CSS
  • JavaScript
  • Mysql
  • PostgreSQL
  • Elasticsearch
  • MongoDB
  • Redis
  • 服务器命令
  • Docker
  • GIT
  • 摄影
  • 草稿
  • 归类方式

    • 分类
    • 标签
    • 归档
  • 关于博客

    • 博客教程
    • 友情链接
    • 关于
导航站
GitHub (opens new window)
  • Python

    • Python学习

      • 特殊方法
      • 常用内置函数
      • 数据类型
      • with用法
      • Python面向对象
      • re正则
      • 线程
      • 进程
      • 协程
      • 装饰器
        • 带参装饰器
        • 不带参装饰器
        • 案例
      • 堆队列heapq
      • 容器collections
      • 内置异常
      • 枚举
      • 好玩的函数
    • 代码

    • 数据结构与算法

  • Django

  • 后端
  • Python
  • Python学习
eastonyangxu
2023-09-04
目录

装饰器

提示

装饰器主要应用场景:包括插入日志、性能测试、事务处理、缓存和权限验证。

在执行某个函数前后,要进行特俗的处理,并且大量的地方需要使用的时候,可以把该逻辑封装为装饰器。

# 带参装饰器

#!/usr/bin/env python
# coding=utf-8
import logging
import time
from functools import wraps


def retry(exception, tries=3, delay=1, back_off=1, logger=None):
    """Retry calling the decorated function using an exponential backoff.

    http://www.saltycrane.com/blog/2009/11/trying-out-retry-decorator-python/
    original from: http://wiki.python.org/moin/PythonDecoratorLibrary#Retry

    :param exception: the exception to check. may be a tuple of
        exceptions to check
    :type exception Exception
    :param tries: number of times to try (not retry) before giving up
    :type tries: int
    :param delay: initial delay between retries in seconds
    :type delay: int
    :param back_off: back off multiplier e.g. value of 2 will double the delay
        each retry
    :type back_off: int
    :param logger: logger to use. If None, print
    :type logger: logging.Logger instance
    """

    def deco_retry(f):
        @wraps(f)
        def f_retry(*args, **kwargs):
            count = 0
            cause = ""
            m_tries, m_delay = tries, delay
            event_name = args[1]
            while m_tries > 1:
                try:
                    count += 1
                    return f(*args, **kwargs)
                except exception as e:
                    cause = e
                    msg = "%s report failed, try again %s times, %s" % (event_name, count, e)
                    if logger:
                        logging.warning(msg)
                    if m_delay > 0:
                        time.sleep(1)
                    m_tries -= 1
                    m_delay *= back_off
            logging.error("%s push failed: %s", event_name, cause)
            return False, True

        return f_retry  # true decorator

    return deco_retry



@retry(2)
def hello():
    """doc"""
    print('hello')


hello()
# 注意加了和不加 @wraps(func) 下面打印的结果
print(hello.__doc__)
print(hello.__name__)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

# 不带参装饰器

def log(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        """打印函数的返回结果"""
        res = func(*args, **kwargs)
        print('函数{}返回的结果为:{}'.format(func.__name__, res))
        return res

    return wrapper


@log
def demo(num1, num2):
    return num1 + num2


@log
def demo1():
    return 'hello world!'


demo(1, 2)
demo1()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 案例

# 登录验证,调用每个接口都会校验是否已登录
token = ''


def login(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        """模拟验证是否登录"""
        if not token:  # 这个token一般是存在数据库(redis/mysql等)的,这里在代码里面模拟写死了
            return '没有登录,请登录后使用'
        return func(*args, **kwargs)

    return wrapper


@login
def post1():
    """模拟一个post请求,调用该请求会先去检查是否登录"""
    pass


@login
def post2():
    """模拟一个post请求,调用该请求会先去检查是否登录"""
    pass


print(post1())
print(post2())

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#Python
上次更新: 2023/09/04, 18:39:45
协程
堆队列heapq

← 协程 堆队列heapq→

最近更新
01
攻略制作要点
07-18
02
摄影主题拍摄
07-18
03
延时摄影剧本
07-18
更多文章>
Theme by Vdoing | Copyright © 2023-2024 Easton Yang | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式