Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Doc/whatsnew/3.9.rst
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ Other Language Changes
ignored for empty strings.
(Contributed by Victor Stinner in :issue:`37388`.)

* ``"".replace("", s, n)`` now returns ``s`` instead of an empty string for
all non-zero ``n``. It is now consistent with ``"".replace("", s)``.
There are similar changes for :class:`bytes` and :class:`bytearray` objects.
(Contributed by Serhiy Storchaka in :issue:`28029`.)


New Modules
===========
Expand Down
1 change: 1 addition & 0 deletions Lib/test/string_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,7 @@ def test_replace(self):
EQ("", "", "replace", "A", "")
EQ("", "", "replace", "A", "A")
EQ("", "", "replace", "", "", 100)
EQ("A", "", "replace", "", "A", 100)
EQ("", "", "replace", "", "", sys.maxsize)

# interleave (from=="", 'to' gets inserted everywhere)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
``"".replace("", s, n)`` now returns ``s`` instead of an empty string for
all non-zero ``n``. There are similar changes for :class:`bytes` and
:class:`bytearray` objects.
13 changes: 5 additions & 8 deletions Objects/stringlib/transmogrify.h
Original file line number Diff line number Diff line change
Expand Up @@ -680,9 +680,13 @@ stringlib_replace(PyObject *self,
const char *to_s, Py_ssize_t to_len,
Py_ssize_t maxcount)
{
if (STRINGLIB_LEN(self) < from_len) {
/* nothing to do; return the original bytes */
return return_self(self);
}
if (maxcount < 0) {
maxcount = PY_SSIZE_T_MAX;
} else if (maxcount == 0 || STRINGLIB_LEN(self) == 0) {
} else if (maxcount == 0) {
/* nothing to do; return the original bytes */
return return_self(self);
}
Expand All @@ -699,13 +703,6 @@ stringlib_replace(PyObject *self,
return stringlib_replace_interleave(self, to_s, to_len, maxcount);
}

/* Except for b"".replace(b"", b"A") == b"A" there is no way beyond this */
/* point for an empty self bytes to generate a non-empty bytes */
/* Special case so the remaining code always gets a non-empty bytes */
if (STRINGLIB_LEN(self) == 0) {
return return_self(self);
}

if (to_len == 0) {
/* delete all occurrences of 'from' bytes */
if (from_len == 1) {
Expand Down
5 changes: 4 additions & 1 deletion Objects/unicodeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -10572,9 +10572,12 @@ replace(PyObject *self, PyObject *str1,
int mayshrink;
Py_UCS4 maxchar, maxchar_str1, maxchar_str2;

if (slen < len1)
goto nothing;

if (maxcount < 0)
maxcount = PY_SSIZE_T_MAX;
else if (maxcount == 0 || slen == 0)
else if (maxcount == 0)
goto nothing;

if (str1 == str2)
Expand Down