Python初学者笔记(四):白话讲正则的“贪婪与懒惰”,你看不懂算我笨!

Python初学者笔记(四):白话讲正则的“贪婪与懒惰”,你看不懂算我笨!
最新回答
蔓草离离

2026-10-22 06:42:36

正则表达式的“贪婪与懒惰”是指匹配模式在满足条件时的行为差异:贪婪模式尽可能匹配最长字符串,懒惰模式尽可能匹配最短字符串。

  • 贪婪模式:在条件允许的前提下,尽可能找更长的匹配。
  • 懒惰模式:在条件允许的前提下,找到第一段符合条件的匹配就行。

下面通过一个生活化的例子来解释这两种模式:

假设有一根金条,上面有黑点,这些黑点将金条分成了几段。现在,你可以和懒汉王二小每人选择一段金条,选择规则是“两个黑点之间”的金条。

  • 王二小(懒惰模式):他看到A和B是两个相邻的黑点,就切了一小块金条(A和B之间的部分)。
  • 你(贪婪模式):你发现A和E也是两个黑点,而且它们之间的距离更远,所以你选择了A和E之间的一大块金条。

在这个例子中,王二小选择了最短的可能匹配(懒惰模式),而你选择了最长的可能匹配(贪婪模式)。

现在,我们将这个概念应用到正则表达式中。在正则表达式中,* 是贪婪模式的代表,它会尽可能多地匹配字符。而 *? 是懒惰模式的代表,它会尽可能少地匹配字符。

下面是一个Python代码示例,展示了贪婪模式和懒惰模式的不同行为:

import redemotext = '''张三李四王二麻子张三的爹李四的爹王二麻子的爹'''# 贪婪模式:从头找到“张字开头,李字结尾”的内容,尽可能找更长的匹配tanlan = re.match('张.*李', demotext)print(tanlan) # 输出: <_sre.SRE_Match object; span=(0, 13), match='张三李四王二麻子张三的爹李'># 懒惰模式:从头找到“张字开头,李字结尾”的内容,找到第一段符合条件的匹配就行landuo = re.match('张.*?李', demotext)print(landuo) # 输出: <_sre.SRE_Match object; span=(0, 3), match='张三李'>

在这个例子中,贪婪模式匹配了从第一个“张”到最后一个“李”之间的所有内容,而懒惰模式只匹配了从第一个“张”到第一个“李”之间的内容。

此外,我们还可以使用 findall 方法来查找所有符合条件的匹配:

import redemotext = '''张三李四王二麻子张三的爹李四的爹王二麻子的爹'''# 贪婪模式:在大字符串内找到全部符合条件的结果,尽可能找更长的匹配tanlan = re.findall('张.*李', demotext)print(tanlan) # 输出: ['张三李四王二麻子张三的爹李']# 懒惰模式:在大字符串内找到全部符合条件的结果,找到第一段符合条件的匹配就行(但会继续查找后续的匹配)landuo = re.findall('张.*?李', demotext)print(landuo) # 输出: ['张三李', '张三的爹李']

在这个例子中,贪婪模式只找到了一个匹配(从第一个“张”到最后一个“李”),而懒惰模式找到了两个匹配(从第一个“张”到第一个“李”,以及从“张三的爹”中的“张”到“李”)。

在实际应用中,应根据具体需求选择贪婪模式或懒惰模式。 如果需要匹配尽可能长的字符串,就使用贪婪模式;如果需要匹配尽可能短的字符串,就使用懒惰模式。