That inner group isn't for capturing... it's just for grouping the alternatives with that | operator.
To make it non-capturing we can put ?: just after the opening paren:
>>> re.findall(r"`((?:\\`|[^`])+)`", text)
['[', ']', '\\`']
Find that hard to read?
I agree.
Remember re.VERBOSE (tip 92)!
Posts by Trey Hunner
We ended up with a list of 2-item tuples.
What's happening is that the re.findall() function only returns strings when there's either no capture group or 1 capture group... but when there are 2 or more capture groups, it returns a tuple of those group matches.
We need a non-capturing group.
We could use a group with an alternative, looking for a \ followed by a backtick OR any non-backtick character: (\\`|[^`])
We could quantify this with + to match it one or more times.
But this doesn't work:
>>> re.findall(r"`((\\`|[^`])+?)`", text)
[('(', '('), (')', ')'), ('\\`', '\\`')]
Python Tip #94 (of 365):
Improve your use of re.findall() with non-capturing groups 🧵
We're modifying our backtick searching regex (tip 93) to work with escaped backticks within backticks, to look for inline code like this:
>>> text = "`(`, `)`, and `\\`` are special."
#Python #DailyPythonTip
Here's a bunch of tips I wish I'd learned before my first one: trey.io/first-pycon
If you can, I'd recommend attending the newcomers orientation on Thursday night.
See you there!
If you're new to your Python journey, I recommend this.
PyCon US is big (~2,000 attendees) which might feel intimidating but it's very likely the friendliest tech conference of its size.
If you attend, come to the newcomers orientation on Thursday if you can.
See you there!
PyCon US 2026 is May 13th to 19th in Long Beach, California. If you've been meaning to learn to program, I'm doing a 3-hour tutorial (additional registration required) for absolute beginners who have never coded before. I hope to see you there! us.pycon.org/2026/
I did not realize I could purchase a PyLadies shirt through my registration ticket this year until I saw this post. It may not have been an option when I signed up or I may have missed it, but it's there now!
Check the dashboard page and add your shirt(s)! 👕👕
us.pycon.org/2026/account...
Note that you COULD argue that the above regex should actually match non-backticks:
>>> re.findall(r"`([^`]*)`", text)
['any()', 'all()']
I can't argue with that.
Reaching for a non-greedy quantifier IS often a sign that there might be a more accurate way to write your regex... but not always.
A greedy quantifier will look for the LONGEST match possible first.
A non-greedy quantifier seeks the SHORTEST match possible.
When there's a chance that there's a difference between the two, you'll probably want the non-greedy one.
That "*" is the problem: it's greedy by default.
Putting a "?" after a quantifier like "*" will make it non-greedy.
This works much better:
>>> re.findall(r"`(.*?)`", text)
['any()', 'all()']
Python Tip #93 (of 365):
Mind the greediness of your regular expression quantifiers 🧵
Let's say you're looking for backtick-surrounded code words in text:
>>> text = "There's `any()` and `all()`."
This won't work well:
>>> re.findall(r"`(.*)`", text)
['any()` and `all()']
#Python #DailyPythonTip
“So the next time you use any form of iteration in Python, remember that under the hood, all iteration does the same thing.”
Read more 👉 pym.dev/all-iteratio...
#Python
Don't use regular expressions for very simple operations.
If the "in" operator or a string method will do what you need in an easier to understand fashion, just use those!
Seem like I'm contradicting tip 89? Check it again. I find those methods less understandable than regular expressions.
Instead of this:
if re.search(r"^http://", string):
Do this:
if string.startswith("http://"):
Instead of this:
if re.search(r"#", string):
Do this:
if "#" in string:
And instead of this:
parts = re.findall(r"\S+", string)
Do this:
parts = string.split()
Python Tip #92 (of 365):
Don't overuse regular expressions 🧵
If a containment check of a common string method will do, don't use a regular expression.
#Python #DailyPythonTip
“There is one feature of self-documenting expressions that I really appreciate: you can put spaces around the equal sign to make the result a little bit more readable.”
Read more 👉 pym.dev/debugging-wi...
#Python
“Iterating over a dictionary object in Python will give you keys, no matter what Python feature you're using to do that iteration.”
Read more 👉 pym.dev/all-iteratio...
#Python
You're welcome!
Python programmers tend to underuse verbose mode when writing regular expressions.
If you're writing a regex that's more complex than \d+, consider using re.VERBOSE.
Your future self (and your teammates) will thank you.
match = re.search(r"""
^ # beginning
\d{2} # 2 digits
[ ] # literal space
[A-Za-z]{3,} # 3 or more letters
[ ] # literal space
\d{4} # 4 digits
$ # end
""", date_string, flags=re.VERBOSE)
Regular expressions are a programming language without comments or whitespace.
That's why I recommend using re.VERBOSE for nearly every regex you write.
But... what if we need to match actual whitespace or a "#" character?
2 options:
1. Escape with a backslash
2. Use a character class: [ ] or [#]
But it gets even better... with re.VERBOSE, you can add comments!
match = re.search(r"""
^ # beginning of the string
\d{5} # 5 digits
( - \d{4} )? # optionally, - followed by 4 digits
$ # end of the string
""", zip_code, flags=re.VERBOSE)
But regular expressions don't have to be so dense!
You can use the re.VERBOSE flag to space them out:
match = re.search(r"""
^
\d{5}
( - \d{4} )?
$
""", zip_code, flags=re.VERBOSE)
This tells Python to ignore whitespace in the regex, so you can add whitespace for readability.
Python Tip #91 (of 365):
Use re.VERBOSE to make your regular expressions more readable 🧵
Regexes are extremely dense: one character is often a whole expression, and they're usually written without whitespace or comments:
match = re.search(r"^\d{5}(-\d{4})?$", zip_code)
#Python #DailyPythonTip
I did better than I expected on this... especially given how infrequently I find myself hand crafting CSS anymore.
I got 51/80.
www.keithcirkel.co.uk/css-or-bs/?r...
#CSSorBS
But a raw string also makes it easier to spot which strings represent regular expressions.
When I see an "r" in front of a string that's used with one of the functions from Python's re module, I assume it's meant to represent a regular expression.
Regular expressions use a lot of "invalid" escape sequence, like "\w", "\d", and "\s" and they sometimes use some valid escape sequence to signify something special ("\b").
Using a raw string will avoid accidentally using a valid escape sequence and avoid trigger syntax warnings.
Python Tip #90 (of 365):
Always use raw strings when defining regular expressions 🧵
I recommend this in order to:
1. Avoid warnings about invalid escape sequences
2. Avoid accidentally using a real escape sequence
3. Clarify which strings are regular expressions
#Python #DailyPythonTip