【问题标题】:Type of compiled regex object in pythonpython中编译的正则表达式对象的类型
【发布时间】:2011-08-31 09:58:25
【问题描述】:

python中编译的正则表达式的类型是什么?

特别想评价一下

isinstance(re.compile(''), ???)

这是真的,出于自省的目的。

我的一个解决方案是,有一些全局常量REGEX_TYPE = type(re.compile('')),但它似乎不是很优雅。

编辑: 我想这样做的原因是因为我有字符串列表和已编译的正则表达式对象。我想将字符串与列表“匹配”,通过

  • 对于列表中的每个字符串,尝试检查字符串是否相等。
  • 对于列表中的每个正则表达式,尝试检查字符串是否与给定模式匹配。

我想出的代码是:

for allowed in alloweds:
    if isinstance(allowed, basestring) and allowed == input:
        ignored = False
        break
    elif isinstance(allowed, REGEX_TYPE) and allowed.match(input):
        ignored = False
        break

【问题讨论】:

  • Python 是关于管道类型的。这违背了 Python 的精神。
  • 这可能是最好的方式如果你真的必须检查类型。据我记得,只有re._pattern_type 可能以下划线开头是有原因的。
  • ad.match(输入) ???你是说 allowed.match(input) 吗?
  • @ultimatebuster: 或者duck taping :)

标签: python regex types


【解决方案1】:

Python 3.5 引入了typing 模块。其中包括typing.Pattern_TypeAlias

从 Python 3.6 开始,您可以这样做:

from typing import Pattern

my_re = re.compile('foo')
assert isinstance(my_re, Pattern)

在 3.5 中,曾经有一个 bug 要求您这样做:

assert issubclass(type(my_re), Pattern)

不保证根据文档和测试套件工作。

【讨论】:

  • 根据链接的问题,此错误似乎已于 2016 年 9 月 27 日修复。
  • 我必须使用from typing import Pattern 才能访问Pattern
  • @Rotareti 谢谢,我认为typing.re 在 3.6 中被删除了
  • 也适用于python2.7
  • Python 2.x 未维护,因此使用它可以被视为安全漏洞。
【解决方案2】:

当某事物的类型没有很好地指定时,使用 type 内置函数在运行时发现答案并没有错:

>>> import re
>>> retype = type(re.compile('hello, world'))
>>> isinstance(re.compile('goodbye'), retype)
True
>>> isinstance(12, retype)
False
>>> 

在运行时发现类型可以保护您不必访问私有属性并防止将来更改返回类型。在这里使用 type 并没有什么不雅之处,尽管想要知道类型可能有些不雅。

也就是说,随着时间的推移,这个问题的背景已经发生了变化。在 Python 的现代版本中,the return type of re.compile 现在是 re.Pattern

如果某事物的类型没有明确指定该怎么办的一般问题仍然有效,但在这种特殊情况下,re.compile(...) 的类型现在已明确指定。 p>

【讨论】:

  • 使用通过这种方法发现的类型并不总是正确的——实现可能使用一种或多种类型来支持给定的特性。不太可能使用正则表达式,但有些工厂现在可能会返回一种类型,以后可能会返回多种类型。但这只是通过检查类型来打破鸭子类型支持期望的另一种形式。
  • 它与其他类型有何不同?你在 Python 中调用的任何东西都可能返回任何东西。这就是为什么想知道类型可能有些不雅
  • @Rosh:这是对 OP 问题的务实回答。让-保罗最后确实说这不是一个好习惯,但作为一个直接的答案,这是一个好习惯。 ++
  • 这不能回答问题
【解决方案3】:

可以将已编译的正则表达式与“re._pattern_type”进行比较

import re
pattern = r'aa'
compiled_re = re.compile(pattern)
print isinstance(compiled_re, re._pattern_type)

>>True

给出 True,至少在 2.7 版中

【讨论】:

  • 这是处理这个问题的理想方法,非常感谢!
【解决方案4】:

免责声明:这并不是针对您的特定需求的直接答案,而是作为替代方法可能有用的东西


您可以保持鸭子类型的理想,并使用hasattr 来确定对象是否具有您想要使用的某些属性。例如,您可以执行以下操作:

if hasattr(possibly_a_re_object, "match"): # Treat it like it's an re object
    possibly_a_re_object.match(thing_to_match_against)
else:
    # alternative handler

【讨论】:

  • 类型提示现在是一件事:)
【解决方案5】:

预防胜于治疗。首先不要创建这样一个异构列表。有一个set 允许的字符串和一个已编译的正则表达式对象列表。这应该使您的检查代码看起来更好并且运行得更快:

if input in allowed_strings:
    ignored = False
else:
    for allowed in allowed_regexed_objects:
        if allowed.match(input):
            ignored = False
            break

如果您无法避免创建这样的列表,请查看您是否有机会检查一次并构建两个替换对象。

【讨论】:

  • 这可能是最理智的答案。
  • for循环可以简化为ignored = not any(allowed.match(input) for allowed in allowed_regexed_objects))
  • 这个答案是建设性的,很好,但它没有回答原始问题。
【解决方案6】:

作为多态性的说明,另一种解决方案是创建实现通用方法的包装类。

class Stringish (str):
    def matches (self, input):
        return self == input

class Regexish (re):
    def matches (self, input):
        return self.match(input)

现在您的代码可以遍历 alloweds 列表,其中包含完全透明地实例化这两个类中的任何一个的对象:

for allowed in alloweds:
    if allowed.matches(input):
        ignored = False
        break

还要注意一些代码重复是如何消失的(尽管您的原始代码可能已被重构以单独修复)。

【讨论】:

  • 出于某种原因,我真的很喜欢这个答案。这确实突出了如何利用鸭子类型来保持 Python 性和抽象性(DRY)。 (我对通用文本搜索也有类似的需求,其中搜索谓词可以是要匹配的字符串列表或正则表达式)。我可能会将str 更改为basestring,因为在Py2 中,unicodestr 都继承自basestring
  • 很遗憾在 Py27 中不起作用,re 是一个无类模块,不能简单地用类继承模型进行扩展。
  • 你可以解决这个问题,它没有re继承;最主要的是要有一个具有两个不同实现的同名方法。
  • 是的,对于Regexish,继承自object,然后只需在__init__ 中调用re 即可通过组合创建re 对象(因为,正如您所说,您只需要实现matchessearch
【解决方案7】:

仅供参考,BeautifulSoup 中有一个此类代码的示例:http://www.crummy.com/software/BeautifulSoup 并使用了“hasattr”技术。 本着“替代方法”的精神,您还可以通过执行以下操作将字符串搜索封装在正则表达式中: 正则表达式 = re.compile(re.escape(your_string)) 因此只有一个正则表达式列表。

【讨论】:

    【解决方案8】:

    在 3.7 中你可以使用re.Pattern:

    import re
    rr = re.compile("pattern")
    isinstance(rr, re.Pattern)
    >> True
    

    【讨论】:

      【解决方案9】:

      这是另一个不是问题的答案,但它解决了问题的回答。除非 your_string 包含正则表达式特殊字符,

      if re.match(your_string,target_string):
      

      效果和

      一样
      if your_string == target_string:
      

      所以退一步,在允许的列表中使用未编译的正则表达式模式。这无疑比使用已编译的正则表达式要慢,但它只适用于偶尔的意外结果,并且只有在您允许用户提供允许的项目时才有效

      【讨论】:

        【解决方案10】:
        >>> import re
        >>> regex = re.compile('foo')
        >>> regex
        <_sre.SRE_Pattern object at 0x10035d960>
        

        嗯 - _sre 是进行模式匹配的 C 扩展...您可以查看 _sre C 源代码。

        你为什么在乎?

        或者您尝试这样的事情(无论出于何种原因 - 我不在乎):

        >>> regex1 = re.compile('bar')
        >>> regex2 = re.compile('foo')
        >>> type(regex1) == type(regex2)
        True
        

        【讨论】:

        • _sre 模块在这里没有这样的属性。
        • @AndreasJung “没有这样的属性”意味着 from _sre import SRE_Pattern 不起作用。反对票可能是 1. 因为你的态度:“我不在乎”——什么? 2. 因为你实际上并没有回答这个问题。
        猜你喜欢
        • 2010-09-09
        • 2012-06-06
        • 2013-01-23
        • 1970-01-01
        • 1970-01-01
        • 2013-08-18
        • 1970-01-01
        • 2017-07-13
        相关资源
        最近更新 更多