Python 3.7.1 findall() 未按预期运行
Python 3.7.1 findall() not behaving as expected
首先,我知道这不是 Python 的当前版本并且 findall() 的行为已从 3.6 更改。我不相信这些都是我遇到的问题。而且我还没有找到关于 findall() 自 3.7 以来发生变化的任何信息。
我已经使用 sub() 而不是 findall() 设计了一个修复程序,但我很好奇为什么我必须首先这样做。
我有一个函数可以检查模式是否存在。如果找到,则应该验证该模式之前是否已定义。目前看起来像这样(修复和一些调试代码):
def _verifyargs(i, end, args):
'''verify text replacement args'''
def _findallfix(m):
formals.append( m.group().upper() )
return '-xxx- '
# put any formal arguments into a more convenient form for checking
checkargs = args.keys()
print( f'checkargs: start={i}, end= {end}, args= {checkargs}' )
# if there aren't any formal arguments we're still checking for
# their improper use within the definition body
while i < end:
i, text = SRC.fetch( i+1 )
SRC.setmaster( i )
formals = []
text = re.sub( SYM.macLabel, _findallfix, text, flags=re.IGNORECASE )
# formals = re.findall( SYM.macLabel, text, flags=re.IGNORECASE )
print( f'line= {i}, formals= {formals}' )
for formal in formals:
# formal = formal.upper()
if not formal in checkargs:
UM.undefined( formal )
SRC.setmaster(end)
模式看起来像这样:
SYM.macLabel = '[?][_A-Z]([.]?[_A-Z0-9])*' # straight text replacement
当运行针对这段测试代码时:
它产生这个输出:
这很好。这就是我想要的。但是如果我注释掉修复:
def _verifyargs(i, end, args):
'''verify text replacement args'''
def _findallfix(m):
formals.append( m.group().upper() )
return '-xxx- '
# put any formal arguments into a more convenient form for checking
checkargs = args.keys()
print( f'checkargs: start={i}, end= {end}, args= {checkargs}' )
# if there aren't any formal arguments we're still checking for
# their improper use within the definition body
while i < end:
i, text = SRC.fetch( i+1 )
SRC.setmaster( i )
# formals = []
# text = re.sub( SYM.macLabel, _findallfix, text, flags=re.IGNORECASE )
formals = re.findall( SYM.macLabel, text, flags=re.IGNORECASE )
print( f'line= {i}, formals= {formals}' )
for formal in formals:
formal = formal.upper()
if not formal in checkargs:
UM.undefined( formal )
SRC.setmaster(end)
...然后测试产生这个:
所以 findall() 似乎进行了意想不到的匹配,尽管我的理解是 sub() 和 findall() 应该具有完全相同的匹配行为。
也许我在滥用 sub()。在这个例子中,我根本不关心替换的结果(我把它保存在这里只是因为我可能想看看它),只关心它找到了我期望的模式。关于 findall() 的工作方式,我是否忽略了什么?
TL;DR
使用 (?: ... )
而不是 ( ... )
因为 re.findall
给你的是捕获组而不是整个匹配项。
详情
这个问题让我有点疑惑,但是我找到了问题所在
documentation for re.findall
说:
The result depends on the number of capturing groups in the pattern.
If there are no groups, return a list of strings matching the whole
pattern. If there is exactly one group, return a list of strings
matching that group. If multiple groups are present, return a list of
tuples of strings matching the groups. Non-capturing groups do not
affect the form of the result.
因为你有一组括号,所以你有一个 captugin 组,这就是 re.findall
正在 returning。它符合您的预期,只是 return 与您的预期不同。
通过使用 non-capturing 括号,(?: ... )
你会得到你想要的结果:全部匹配。
即:
SYM.macLabel = '[?][_A-Z](?:[.]?[_A-Z0-9])*'
首先,我知道这不是 Python 的当前版本并且 findall() 的行为已从 3.6 更改。我不相信这些都是我遇到的问题。而且我还没有找到关于 findall() 自 3.7 以来发生变化的任何信息。
我已经使用 sub() 而不是 findall() 设计了一个修复程序,但我很好奇为什么我必须首先这样做。
我有一个函数可以检查模式是否存在。如果找到,则应该验证该模式之前是否已定义。目前看起来像这样(修复和一些调试代码):
def _verifyargs(i, end, args):
'''verify text replacement args'''
def _findallfix(m):
formals.append( m.group().upper() )
return '-xxx- '
# put any formal arguments into a more convenient form for checking
checkargs = args.keys()
print( f'checkargs: start={i}, end= {end}, args= {checkargs}' )
# if there aren't any formal arguments we're still checking for
# their improper use within the definition body
while i < end:
i, text = SRC.fetch( i+1 )
SRC.setmaster( i )
formals = []
text = re.sub( SYM.macLabel, _findallfix, text, flags=re.IGNORECASE )
# formals = re.findall( SYM.macLabel, text, flags=re.IGNORECASE )
print( f'line= {i}, formals= {formals}' )
for formal in formals:
# formal = formal.upper()
if not formal in checkargs:
UM.undefined( formal )
SRC.setmaster(end)
模式看起来像这样:
SYM.macLabel = '[?][_A-Z]([.]?[_A-Z0-9])*' # straight text replacement
当运行针对这段测试代码时:
它产生这个输出:
这很好。这就是我想要的。但是如果我注释掉修复:
def _verifyargs(i, end, args):
'''verify text replacement args'''
def _findallfix(m):
formals.append( m.group().upper() )
return '-xxx- '
# put any formal arguments into a more convenient form for checking
checkargs = args.keys()
print( f'checkargs: start={i}, end= {end}, args= {checkargs}' )
# if there aren't any formal arguments we're still checking for
# their improper use within the definition body
while i < end:
i, text = SRC.fetch( i+1 )
SRC.setmaster( i )
# formals = []
# text = re.sub( SYM.macLabel, _findallfix, text, flags=re.IGNORECASE )
formals = re.findall( SYM.macLabel, text, flags=re.IGNORECASE )
print( f'line= {i}, formals= {formals}' )
for formal in formals:
formal = formal.upper()
if not formal in checkargs:
UM.undefined( formal )
SRC.setmaster(end)
...然后测试产生这个:
所以 findall() 似乎进行了意想不到的匹配,尽管我的理解是 sub() 和 findall() 应该具有完全相同的匹配行为。
也许我在滥用 sub()。在这个例子中,我根本不关心替换的结果(我把它保存在这里只是因为我可能想看看它),只关心它找到了我期望的模式。关于 findall() 的工作方式,我是否忽略了什么?
TL;DR
使用 (?: ... )
而不是 ( ... )
因为 re.findall
给你的是捕获组而不是整个匹配项。
详情
这个问题让我有点疑惑,但是我找到了问题所在
documentation for re.findall
说:
The result depends on the number of capturing groups in the pattern. If there are no groups, return a list of strings matching the whole pattern. If there is exactly one group, return a list of strings matching that group. If multiple groups are present, return a list of tuples of strings matching the groups. Non-capturing groups do not affect the form of the result.
因为你有一组括号,所以你有一个 captugin 组,这就是 re.findall
正在 returning。它符合您的预期,只是 return 与您的预期不同。
通过使用 non-capturing 括号,(?: ... )
你会得到你想要的结果:全部匹配。
即:
SYM.macLabel = '[?][_A-Z](?:[.]?[_A-Z0-9])*'