wrong signature
def find_and_replace(pattern: str, ...
You intended pattern: re.Pattern,
Recommend you routinely use mypy
or similar type checker if you choose to add optional type annotations.
It is common knowledge that "Comments lie!". Often they're initially accurate, and then the code evolves with edits while the comments remain mired in the past, out of sync. So at best we will "mostly believe" the comments that appear.
A type signature offers stronger promises, since we expect that lint nonsense was cleaned up during routine edit-debug and CI/CD cycles. Posting code for review which doesn't meet that expectation is problematic.
wrong code
last_end = end
You intended to assign ... = match.end()
. I cannot imagine how one could "test" this source code without noticing a fatal NameError.
missing documentation
The review context merely mentioned that this will "search and replace strings", similar to what the identifier promises. It's unclear how the proposed functionality would differ from what the str or re libraries offer, though the signature does offer a hint. The hint is not enough, and we are not even offered so much as a motivating example of the kinds of Turing machines we might usefully pass in.
missing test suite
This submission contained no doctest, no automated tests of any kind. One reason we write tests is to exercise the code, for example to discover a NameError. Another reason is to educate engineers who might want to call into this library routine.
Here is a test that might usefully have been included in the OP.
import unittest class FindAndReplaceTest(unittest.TestCase): def test_find_and_replace(self) -> None: pattern = re.compile(r"\w+") text = "... Hello, world!" def replace(match: re.Match) -> str: return "<" + str(match.group(0).upper()) + ">" self.assertEqual( "... <HELLO>, <WORLD>!", find_and_replace(pattern, text, replace), )
superfluous tests
if text_before: output.append(text_before) ... if text_remaining: output.append(text_remaining)
There's no need to test for non-empty, as empty string is the additive identity when catenating. The ''.join(output)
result won't be altered in the slightest if we tack on a hundred empty entries with:
output += [""] * 100
So as a minor cleanup, simply elide the if
s.
PATTERN
come from? And are you missing any imports? (re
perhaps?)\$\endgroup\$PATTERN
should obviously be a parameter and the checks to not append empty strings tooutput
are redundant. Apart from that, the implementation is easy to follow, so nothing I would obsess about.\$\endgroup\$re
andtyping.Callable
need to be imported. AndPATTERN
should be a parameter, as @uli correctly pointed out. I changed the code accordingly.\$\endgroup\$end
is undefined. Don't omit important code for the sake of simplicity.\$\endgroup\$