Union[s-6ren">
gpt4 book ai didi

python - 正则表达式匹配联合类型的 "|"分隔值

转载 作者:行者123 更新时间:2023-12-04 13:24:12 25 4
gpt4 key购买 nike

我正在尝试匹配类型注释,如 int | str ,并使用正则表达式替换将它们替换为字符串 Union[int, str] .
所需的替换(之前和之后):

  • str|int|bool -> Union[str,int,bool]
  • Optional[int|tuple[str|int]] -> Optional[Union[int,tuple[Union[str,int]]]]
  • dict[str | int, list[B | C | Optional[D]]] -> dict[Union[str,int], list[Union[B,C,Optional[D]]]]

  • 到目前为止,我想出的正则表达式如下:
    r"\w*(?:\[|,|^)[\t ]*((?'type'[a-zA-Z0-9_.\[\]]+)(?:[\t ]*\|[\t ]*(?&type))+)(?:\]|,|$)"
    你可以试试 here on Regex Demo .它并没有像我想要的那样工作。到目前为止我注意到的问题:
  • 到目前为止,它似乎还没有处理嵌套的联合条件。例如,int | tuple[str|int] | bool似乎导致一场比赛,而不是两场比赛(包括内部联盟条件)。
  • 正则表达式似乎消耗了不必要的 ]在末尾。
  • 可能是最重要的一个,但我注意到 re 似乎不支持正则表达式子例程。 Python 中的模块。 Here是我想到使用它的地方。

  • 附加信息
    这个主要是为了支持 PEP 604 Python 3.7+ 的语法,它需要预先声明注释(例如声明为字符串)才能被支持,否则内置类型不支持 |运算符(operator)。
    这是我想出的示例代码:
    from __future__ import annotations

    import datetime
    from decimal import Decimal
    from typing import Optional


    class A:
    field_1: str|int|bool
    field_2: int | tuple[str|int] | bool
    field_3: Decimal|datetime.date|str
    field_4: str|Optional[int]
    field_5: Optional[int|str]
    field_6: dict[str | int, list[B | C | Optional[D]]]

    class B: ...
    class C: ...
    class D: ...
    对于 3.10 之前的 Python 版本,我使用 __future__导入以避免以下错误:
    TypeError: unsupported operand type(s) for |: 'type' and 'type'
    这基本上将所有注释转换为字符串,如下所示:
    >>> A.__annotations__
    {'field_1': 'str | int | bool', 'field_2': 'int | tuple[str | int] | bool', 'field_3': 'Decimal | datetime.date | str', 'field_4': 'str | Optional[int]', 'field_5': 'Optional[int | str]', 'field_6': 'dict[str | int, list[B | C | Optional[D]]]'}
    但是在代码中(比如在另一个模块中),我想评估 A 中的注释。这在 Python 3.10 中有效,但在 Python 3.7+ 中失败,即使 __future__ import 支持前向声明的注释。
    >>> from typing import get_type_hints
    >>> hints = get_type_hints(A)

    Traceback (most recent call last):
    eval(self.__forward_code__, globalns, localns),
    File "<string>", line 1, in <module>
    TypeError: unsupported operand type(s) for |: 'type' and 'type'
    似乎使这项工作的最佳方法是替换所有出现的 int | str (例如)与 Union[int, str] ,然后用 typing.Union包含在附加 localns 中用于评估注释,然后应该可以评估 Python 3.7+ 的 PEP 604 样式的注释。

    最佳答案

    您可以安装 PyPi regex模块(如 re 不支持递归)并使用

    import regex
    text = "str|int|bool\nOptional[int|tuple[str|int]]\ndict[str | int, list[B | C | Optional[D]]]"
    rx = r"(\w+\[)(\w+(\[(?:[^][|]++|(?3))*])?(?:\s*\|\s*\w+(\[(?:[^][|]++|(?4))*])?)+)]"
    n = 1
    res = text
    while n != 0:
    res, n = regex.subn(rx, lambda x: "{}Union[{}]]".format(x.group(1), regex.sub(r'\s*\|\s*', ',', x.group(2))), res)

    print( regex.sub(r'\w+(?:\s*\|\s*\w+)+', lambda z: "Union[{}]".format(regex.sub(r'\s*\|\s*', ',', z.group())), res) )
    输出:
    Union[str,int,bool]
    Optional[Union[int,tuple[Union[str,int]]]]
    dict[Union[str,int], list[Union[B,C,Optional[D]]]]
    Python demo .
    first regex查找各种 WORD[...]包含管道字符和其他 WORD s 或 WORD[...]里面没有管道字符。 \w+(?:\s*\|\s*\w+)+ regex匹配 2 个或更多由竖线和可选空格分隔的单词。
    第一个图案细节:
  • (\w+\[) - 第 1 组(在替换开始时将保持原样):一个或多个单词字符,然后是 [字符
  • (\w+(\[(?:[^][|]++|(?3))*])?(?:\s*\|\s*\w+(\[(?:[^][|]++|(?4))*])?)+) - 第 2 组(将放在 Union[...] 内,所有 \s*\|\s* 模式都替换为 , ):
  • \w+ - 一个或多个字字符
  • (\[(?:[^][|]++|(?3))*])? - 与 [ 匹配的可选组 3字符,后跟零个或多个出现的一个或多个 []字符或整个第 3 组递归(因此,它匹配嵌套括号),然后是 ]字符
  • (?:\s*\|\s*\w+(\[(?:[^][|]++|(?4))*])?)+ - 一次或多次出现(因此匹配包含至少一个管道字符以替换为 , ):
  • \s*\|\s* - 用零个或多个空格包围的管道字符
  • \w+ - 一个或多个字字符
  • (\[(?:[^][|]++|(?4))*])? - 可选的第 4 组(与第 3 组匹配,注意 (?4) 子程序重复第 4 组模式)


  • ] - 一个 ]字符。
  • 关于python - 正则表达式匹配联合类型的 "|"分隔值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69606986/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com