如何用Python re.sub实现iframe连续编号?解决变量绑定错误
Let's break down why you're running into these errors and fix them with clean, concise solutions that fit your requirements.
Why the Original Code Fails
When you write num = num + 1 inside your regex function, Python automatically treats num as a local variable. But you’re trying to reference num (on the right side of the assignment) before it’s defined locally—hence the UnboundLocalError.
Your attempt to use global was on the right track, but you had the order wrong: you can’t assign to num before declaring it as global.
Solution 1: Correct Global Variable Usage
Fix the global declaration order, and adjust your regex to properly capture full URLs (your original (\w+) won’t match URLs with :// or dots):
import re num = 0 def regex_match(m): global num # Declare num as global FIRST num += 1 # Use f-strings for cleaner, more readable formatting return f'<iframe src="{m.group(1)}/number/{num}">' source = '<p>hogehogehello<br />aaaa</p><iframe src="https://youtube.com/hogehgoe"><div><strong><h1>aa</h1></strong></div><iframe src="https://youtube.com/foo"><iframe src="https://youtube.com/bar"><h2>aaaaaa</h2><iframe src="https://youtube.com/baz">' processed_source = re.sub(r'<iframe src="([^"]+)">', regex_match, source) print(processed_source)
This will output exactly what you want, with each iframe's src appended with /number/1, /number/2, etc.
Solution 2: Cleaner Approach Without Global Variables (Shorter Code)
Global variables can introduce unwanted side effects, so a better (and shorter) way is to use itertools.count to create an auto-incrementing iterator. This avoids global variables entirely and keeps your code tight:
import re from itertools import count source = '<p>hogehogehello<br />aaaa</p><iframe src="https://youtube.com/hogehgoe"><div><strong><h1>aa</h1></strong></div><iframe src="https://youtube.com/foo"><iframe src="https://youtube.com/bar"><h2>aaaaaa</h2><iframe src="https://youtube.com/baz">' # Create a counter starting at 1 counter = count(1) # Use a lambda to handle matches and increment the counter on each hit processed_source = re.sub(r'<iframe src="([^"]+)">', lambda m: f'<iframe src="{m.group(1)}/number/{next(counter)}">', source) print(processed_source)
How This Works:
count(1)generates an infinite iterator that starts at 1 and increments by 1 each time you callnext()on it.- The lambda function runs once per match, calling
next(counter)to get the next sequential number and inserting it into the replacement string.
This is the shortest, most maintainable solution that meets your "no finditer" requirement.
内容的提问来源于stack exchange,提问作者Clifford Fox

