使用 python 函数签名自动生成默认返回值

入职新公司之后一直致力于bug修复以及新功能开发, 所以很久没有写笔记了

使用 python 函数签名自动生成默认返回值

  • 先说一下使用场景吧 数据完整性要求不高,但是又不能影响下游

  • 一般来说都是配合retry食用

  • 具体使用场景俺也不清楚, 仁者见仁智者见智吧, 或者魔改一下呢

from typing import Tuple
def run_func():
    @retry(max_retries=1, delay=1)
    def example_function() -> Tuple[str, str]:
    
        # 假设这里抛出了异常, 但是返回值又是元组, 则会导致下游解包错误
        raise TypeError('111')

    print(example_function())
# 当然, 你也可以在外层加入判断或者别的方式去做, 但是总觉得少了点什么
  • 再说下代码编写的格式吧

  • 要遵循手动 类型标注 并且复杂类型要遵循typing 方式去做

  • 可能兼容的类型不全或者有bug, 但是原理是有了, 增加自己需要兼容的返回值类型就可以了

  • 接下来上代码(纯属笔记)

# -*- coding: UTF-8 -*-
# @author: ylw
# @file: demo
# @time: 2024/6/28
# @desc:
# import sys
# import os

# F_PATH = os.path.dirname(__file__)
# sys.path.append(os.path.join(F_PATH, '..'))
# sys.path.append(os.path.join(F_PATH, '../..'))
import time
import typing
import traceback
import inspect
from functools import wraps

DEFAULT_VALUES = {
    int: 0,
    float: 0.0,
    str: '',
    list: [],
    dict: {},
    tuple: (),
    set: set(),
    bool: False,
    None: None
}


def generate_default_value(return_type: typing.Any) -> typing.Any:
    """
    根据返回类型生成默认值
    生效条件为手动添加了函数签名(返回值类型)
    :param return_type:
        inspect.signature(func).return_annotation
    """
    if return_type in DEFAULT_VALUES:
        return DEFAULT_VALUES[return_type]
    elif isinstance(return_type, getattr(typing, '_GenericAlias')):
        origin = return_type.__origin__
        args = typing.get_args(return_type)

        if origin is typing.Union:
            return generate_default_value(args[0])
        elif origin is list:
            return [generate_default_value(args[0])] if args else []
        elif origin is dict:
            return {generate_default_value(args[0]): generate_default_value(args[1])} if len(args) == 2 else {}
        elif origin is tuple:
            return tuple(generate_default_value(arg) for arg in args)
        elif origin is set:
            return set(generate_default_value(arg) for arg in args[0]) if args else set()
        elif origin is typing.Tuple:
            return tuple(DEFAULT_VALUES.get(arg, None) for arg in args)
    return None


def get_traceback_str(error: Exception) -> str:
    return '\n'.join([i.strip().replace('    ', '  ') for i in traceback.format_tb(error.__traceback__)])


def retry(max_retries=3, delay=0, *, save_error_log: bool = True, no_exception=False):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            error = None
            for attempt in range(max_retries):
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    if save_error_log:
                        tb = get_traceback_str(e)
                        print(f"{tb}\n{attempt + 1}/{max_retries}")
                    if delay > 0:
                        time.sleep(delay)
                    error = e
            if no_exception:
                sig = inspect.signature(func)
                return generate_default_value(sig.return_annotation)
            raise error

        return wrapper

    return decorator


def run_func():
    # 示例函数
    @retry(1, 1, no_exception=True)
    def example_function() -> typing.Tuple[None, str]:
        raise TypeError('111')

    print(example_function())


if __name__ == '__main__':
    run_func()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值