python中已编译的regex对象的类型


74

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

3
Python全部与风管类型有关。这违反了Python的精神。
Pwnna

3
如果您真的必须检查类型,那可能是最好的方法。据我所知,只有re._pattern_type一个原因可能是下划线开头。

ad.match(input)??? 你的意思是allowed.match(输入)?
约翰·马钦

3
@ultimatebuster:或者duck taping:)
John Machin

我非常喜欢SO:每次遇到问题时,无论多么具体或晦涩,都会有SO的答案。我最好还是搜索SO而不是Google。
bgw 2011年

Answers:


40

如果没有明确指定某种类型,则使用type内置函数在运行时发现答案没有任何问题:

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

在运行时发现类型可以防止您访问私有属性以及将来对返回类型的更改。在type这里使用并没有什么不好的地方,尽管可能根本不想知道类型。

也就是说,随着时间的流逝,这个问题的背景发生了变化。在现代版本的Python中,return类型re.compile为now re.Pattern

关于做什么,如果东西的类型没有被很好地规定的一般问题仍然是有效的,但在这种特殊情况下,类型re.compile(...) 现在人们所指定。


12
使用通过这种方法发现的类型并不总是正确的-实现可能使用一种或多种类型来支持给定的功能。正则表达式不太可能,但是有些工厂可能现在返回一种类型,以后又返回许多类型。但这只是通过检查类型打破鸭子输入支持预期的另一种形式。
Rosh Oxymoron

1
与其他类型有什么不同?您在Python中调用的任何内容都可能返回其他内容。这就是为什么根本不想知道类型的原因
Jean-Paul Calderone

4
@Rosh:这是对OP问题的务实回答。让·保罗确实说这最终不是一个好习惯,但是作为直接回答,这是一个好习惯。++
Eli Bendersky

这不能回答问题
xaxxon '19

62

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中,曾经有一个错误要求您执行以下操作:

assert issubclass(type(my_re), Pattern)

根据文档和测试套件,不能保证可以正常工作。


2
根据链接的问题,此错误似乎已于2016-09-27修复。
迈克尔·巴顿

6
我必须使用from typing import Pattern才能访问Pattern
Rotareti

@Rotareti谢谢,typing.re我想在3.6中被删除
飞羊

21

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

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

>>True

至少在2.7版中为True


这是处理此问题的理想方法,非常感谢!
Jamie Ivanov '18

16

免责声明:这并不是要直接满足您的特定需求,而是可以作为一种替代方法使用


您可以保持鸭子输入的理想状态,并用于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

现在,类型提示已成为问题:)
Cedric H.

10

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

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

如果无法避免创建此类列表,请查看是否有机会对其进行一次检查并构建两个替换对象。


这可能是最理智的答案。
Jeeyoung Kim 2011年

1
for循环可以简化为ignored = not any(allowed.match(input) for allowed in allowed_regexed_objects))
Sven Marnach 2011年

2
这个答案是建设性的,很好,但是不能回答原始问题。
泰勒2012年

7

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

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

还请注意,某些代码重复的方式消失了(尽管您的原始代码可能已经被重构以单独修复)。


由于某些原因,我真的很喜欢这个答案。这确实突出了如何利用鸭式输入来保持pythonicity和abstract(DRY)。(对于通用文本搜索,我也有类似的需求,其中搜索谓词可以是要匹配的字符串列表或正则表达式)。我可能会改变str,以basestring自种的Py2,都unicodestr继承basestring
Cowbert

不幸的是,它在Py27中不起作用,它re是无法通过类继承模型简单扩展的无类模块。
Cowbert

1
您可以解决的是,它不具有从继承re; 最主要的是拥有一个具有两个不同实现的同名方法。
Tripleee'December

是啊的Regexish,继承object,然后只需调用re__init__创建一个re由组成(因为,如你所说,你只需要实现目标matchessearch
cowbert

3

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


1

在3.7中,您可以使用re.Pattern

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

0

不是问题的答案,而是解决问题的答案。除非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模块在这里没有这样的属性。
Rosh Oxymoron

1
@AndreasJung“没有这样的属性”表示from _sre import SRE_Pattern不起作用。下选票可能是1.由于您的态度:“我不在乎” –什么?2.因为您实际上没有回答问题。
飞羊
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.