Skip to content

Commit

Permalink
Make the specification more concise (python#1344)
Browse files Browse the repository at this point in the history
  • Loading branch information
sweeneyde committed Mar 27, 2020
1 parent f53a04e commit 164f8fa
Showing 1 changed file with 7 additions and 40 deletions.
47 changes: 7 additions & 40 deletions pep-0616.rst
Expand Up @@ -49,8 +49,8 @@ requires a module import, and results in less readable code.
Specification
=============

The builtin ``str`` class will gain two new methods with roughly the
following behavior::
The builtin ``str`` class will gain two new methods which will behave
as follows when ``type(self) is type(prefix) is type(suffix) is str``::

def removeprefix(self: str, prefix: str, /) -> str:
if self.startswith(prefix):
Expand All @@ -59,45 +59,20 @@ following behavior::
return self[:]

def removesuffix(self: str, suffix: str, /) -> str:
# suffix='' should not call self[:-0].
if suffix and self.endswith(suffix):
return self[:-len(suffix)]
else:
return self[:]

Note that ``self[:]`` might not actually make a copy -- if the affix
is empty or not found, and if ``type(self) is str``, then these methods
may, but are not required to, make the optimization of returning ``self``.
However, when called on instances of subclasses of ``str``, these
methods should return base ``str`` objects, not ``self``.

Without the check for the truthiness of ``suffix``,
``s.removesuffix('')`` would be mishandled and always return the empty
string due to the unintended evaluation of ``self[:-0]``.
These methods, even when called on ``str`` subclasses, should always
return base ``str`` objects.

Methods with the corresponding semantics will be added to the builtin
``bytes`` and ``bytearray`` objects. If ``b`` is either a ``bytes``
or ``bytearray`` object, then ``b.removeprefix()`` and ``b.removesuffix()``
will accept any bytes-like object as an argument. Although the methods
on the immutable ``str`` and ``bytes`` types may make the aforementioned
optimization of returning the original object, ``bytearray.removeprefix()``
and ``bytearray.removesuffix()`` should *always* return a copy, never the
original object.

To test whether any affixes were removed during the call, users
may use the constant-time behavior of comparing the lengths of
the original and new strings::

>>> string = 'Python String Input'
>>> new_string = string.removeprefix('Py')
>>> modified = (len(string) != len(new_string))
>>> modified
True

Users may also continue using ``startswith()`` and ``endswith()``
methods for control flow instead of testing the lengths as above.

The two methods will also be added to ``collections.UserString``, with
similar behavior.
will accept any bytes-like object as an argument. The two methods will
also be added to ``collections.UserString``, with similar behavior.


Motivating examples from the Python standard library
Expand Down Expand Up @@ -233,14 +208,6 @@ expansion of the ``lstrip``/``rstrip`` API -- repeatedly applying the
function until the argument is unchanged. This behavior is attainable
from the proposed behavior via by the following::

>>> s = 'Foo' * 100 + 'Bar'
>>> prefix = 'Foo'
>>> while len(s) != len(s := s.removeprefix(prefix)): pass
>>> s
'Bar'

or the more obvious and readable alternative::

>>> s = 'Foo' * 100 + 'Bar'
>>> prefix = 'Foo'
>>> while s.startswith(prefix): s = s.removeprefix(prefix)
Expand Down

0 comments on commit 164f8fa

Please sign in to comment.