思考练习:什么是最好的"编写Python函数的方法,该函数采用正则表达式或字符串来完全匹配:
import re
strings = [...]
def do_search(matcher):
"""
Returns strings matching matcher, which can be either a string
(for exact match) or a compiled regular expression object
(for more complex matches).
"""
if not is_a_regex_pattern(matcher):
matcher = re.compile('%s$' % re.escape(matcher))
for s in strings:
if matcher.match(s):
yield s
那么,实施is_a_regex_pattern()
?
答案 0 :(得分:6)
您可以通过_sre.SRE_Pattern
:
re._pattern_type
类型
if not isinstance(matcher, re._pattern_type):
matcher = re.compile('%s$' % re.escape(matcher))
以下是演示:
>>> import re
>>> re._pattern_type
<class '_sre.SRE_Pattern'>
>>> isinstance(re.compile('abc'), re._pattern_type)
True
>>>
答案 1 :(得分:0)
不是字符串:
def is_a_regex_pattern(s):
return not isinstance(s, basestring)
是_sre.SRE_Pattern
(虽然这不可导入,但使用粗字符串匹配):
def is_a_regex_pattern(s):
return s.__class__.__name__ == 'SRE_Pattern'
您可以重新编译SRE_Pattern,似乎来评估它。
def is_a_regex_pattern(s):
return s == re.compile(s)
答案 2 :(得分:0)
如果matcher
有方法match
:
import re
def do_search(matcher, strings):
"""
Returns strings matching matcher, which can be either a string
(for exact match) or a compiled regular expression object
(for more complex matches).
"""
if hasattr(matcher, 'match'):
test = matcher.match
else:
test = lambda s: matcher==s
for s in strings:
if test(s):
yield s
您不应使用全局变量,而是使用第二个参数。
答案 3 :(得分:0)
或者,将其设为quack:
try:
does_match = matcher.match(s)
except AttributeError:
does_match = re.match(matcher.s)
if does_match:
yield s
换句话说,将matcher
视为已经是已编译的正则表达式。如果那样中断,那就把它当作需要编译的字符串来对待。
这称为Duck Typing。不是每个人agrees都应该像常规突发事件那样使用例外情况。这是ask-permission versus ask-forgiveness辩论。与大多数语言相比,Python的宽恕程度要高amenable。
答案 4 :(得分:0)
在 Python 3.7 上,re._pattern_type
被重命名为 re.Pattern
https://stackoverflow.com/a/27366172/895245 因此在那时中断,因为 re._pattern_type
未定义。
虽然 re.Pattern
看起来更好,因此有望更稳定,但文档中根本没有提到它:https://docs.python.org/3/library/re.html#regular-expression-objects 所以依赖它可能不是一个好主意。
https://stackoverflow.com/a/46779329/895245 确实有些道理。但是哪一天 str
类添加了一个 .match
方法,它会做一些完全不同的事情? :-) 啊,无类型语言的乐趣。
所以我想我会去:
import re
_takes_s_or_re_type = type(re.compile(''))
def takes_s_or_re(s_or_re):
if isinstance(s_or_re, _takes_s_or_re_type):
return 0
else:
return 1
assert takes_s_or_re(re.compile('a.c')) == 0
assert takes_s_or_re('a.c') == 1
因为这只会在公共 API 中断时中断。
在 Python 3.8.0 上测试。