'Why does Python's str.partition return the separator?

I use Python's str.partition in my code in three ways:

before, __, after = string.partition(sep)
before = string.partition(sep)[0]
after = string.partition(sep)[2]

While I use str.partition frequently, I've always wondered why it returns the separator. The first line surely would benefit from it not returning the separator, and in my opinion, also the third line would become more intuitive.

While I acknowledge that one can re-build the string with

"".join(string.partition(sep))

I do not see any use case for this.

So, what is the rationale of the inclusion of the separator in the returned tuple?



Solution 1:[1]

Per the documentation, str.partition and the associated str.rpartition were:

New in version 2.5.

Looking at the what's new for that version provides some rationale for these methods, which "simplify a common use case":

The find(S)() method is often used to get an index which is then used to slice the string and obtain the pieces that are before and after the separator. partition(sep)() condenses this pattern into a single method call that returns a 3-tuple containing the substring before the separator, the separator itself, and the substring after the separator.


Looking at some of the examples originally provided when the function was developed, e.g. replacing:

i = host.find(':')
if i >= 0:
    port = host[i+1:]
    ...

with:

_, sep, port = host.partition(':')
if sep:
    ...

including sep in the output makes it easy to check whether it was found in the string. There are various examples that use only two of the three returned values, but which they don't need varies!

Solution 2:[2]

Following jonrsharpe's lead, I found this mail from Raymond Hettinger. It explains the rationale and shows many use cases. The middle value can be used as a boolean flag, and they were even close to calling it "found" instead of "sep". And in almost all of his many examples where the middle value isn't ignored, it's indeed used as a boolean flag (and sometimes also used further). The "old pattern" had been to call find, check < 0 or >= 0, and then conditionally extract the parts. The new partition function replaced that pattern well. A typical example:

Old:

i = p.find('=')
if i >= 0:
    name = p[:i]
    value = p[i+1:]
    (use name and value)

New:

name, found, value = p.partition('=')
if found:
    (use name and value)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2