Method for reversing strings

@Rosuav I am not saying reversing things is trivial and there are no gotchas. What I am saying is that [::-1] solves that problem already:


Awesome! No worries. Let’s use it to make the language more readable and user friendly? My concern with this topic is probably more along the lines of precisely 2 strings:
[::-1] vs reverse()
I know every regular in the python.org discussion board is probably comfortable with the former. I just think the latter could be better.

Thanks for that:


I also liked the Rationale section. It takes a quick search on your favorite search engine to determine how often python string reverse is used. I cannot speak as to why they all use it. I use it for test data and munging data.

If you need to qualify a statement with “no offense” and a smiling emoji, it’s probably an offensive statement and should not be made.

4 Likes

This basically translates to “I prefer .reverse()”. Unfortunately, just because someone prefers a particular spelling isn’t a good enough reason for a language change (in this case a change to a builtin class). You’ll need much better arguments in favour of this change if you want it to get anywhere.

Remember, if this went ahead, all the documentation would nee updating, tutorials and courses would need amending, people maintaining linters and style guides would have to decide whether to promote .reverse() over [::-1], people writing classes intended to “work like str” would have to add the new method, etc, etc. It’s surprising how much work is needed even for a change that’s simple on the face of it. And unless the benefit outweighs that work, it’s hard to justify the proposal.

6 Likes

Let’s take the top stackoverflow question from there and scroll down a bit to the first answer that actually considers the complications: How do I reverse a string in Python? - Stack Overflow

It gives the following example:

example = "👈🏾👆"

Which clearly shows that reversing a string is not a trivial operation. Neither is slicing a string. [1] This is what @Rosuav was trying to tell you, they just chose a somewhat poor example.

There is a trivial pattern you can do: [::-1]. This generally works, but is wrong for edge cases. IMO if we were to add a method, it should handle edge cases “correctly” - I don’t believe python currently has enough knowledge built in to figure out how to reverse the above string correctly, nor do I think python should guess about what correct means in your context. If you need to reverse a string, implement a function that does exactly what you need - if it is [::-1], great, use that.


  1. i.e. look at example[1] ↩︎

5 Likes

Well, also list[:] produces a shallow copy of a list, but we have also list.copy().

The real question is: what is the use case of str[::-1]?

1 Like

(It’s a pain working with these images, can you use text please?)

Perhaps you didn’t read what I said. [::-1] does NOT completely solve the problem. Observe:

>>> "dalokoš"[::-1]
'šokolad'
>>> "dalokoš"[::-1]
'̌sokolad'

Can you tell the difference between the two inputs? Because the outputs are definitely different. Here, I’ll make it easier:

>>> "daloko\u0161"[::-1]
'šokolad'
>>> "dalokos\u030c"[::-1]
'̌sokolad'

Cornelius gave another example where reversing the string codepoint-by-codepoint does not do what people would intuitively expect, and I think it’s actually a better example for this:

In my examples, the result of reversing the string is a broken string. In this one, it’s a shift of semantics.

>>> "👈🏾👆"[::-1]
'👆🏾👈'

Reversing is not trivial.

7 Likes

Just in case you didn’t notice, it appears discourse somehow manages to fix this. So maybe sharing an image would be a good idea in this case…

(or if you are still seeing the broken stuff, it’s somehow OS/browser dependent - I can reproduce the broken result in the python terminal)

1 Like

Ugh, I was convinced Python automatically reversed combining characters as a unit. This almost argues for having a unicodedata.reversed() function

4 Likes

ehh, that’s why I provided the version with the escapes - people can do it themselves on their own computers. Though when I look at it, the second one is definitely messed up. (I wouldn’t be surprised if the two inputs end up identical after going through Discourse’s database, but the outputs shouldn’t.)

Well, it this works to you, use [::-1]. But many users can expect different behavior from the string reverting function.

Python does not, but users do. I mentioned emoji. @MegaIng already shown an example, here is other:

>>> '🇺🇦'[::-1]
'🇦🇺'
6 Likes

Hmm, this raises terminology problems. I specifically said “code units” which are based on a particular encoding, differentiating from “code points” which are independent of that. But what do you call the things that cannot possibly be characters on their own? The flag example is a good one. If you have just one of those, it’s not a valid character: 🇺 But I think it’s still a code point, just not a character.

Terminology is hard too.

1 Like

This sent me down a dark hole into unicode and graphemes. It might be good to have a reversed function for unicode strings that splits by graphemes rather than “characters” for reversal.
It seems there is an existing library that could form the basis of this, but would it, (a builtin), be used enough to be worth the extra work over just using this external library?


# %%

import grapheme

def reverse_graphemes(s: str) -> str:
    "Reverse string by grapheme"
    return ''.join([g for g in grapheme.graphemes(s)][::-1])
    
example = 'Foo 👈🏾 bar 👆 baz'

# All assertions pass
assert reverse_graphemes(example) == 'zab 👆 rab 👈🏾 ooF'
assert reverse_graphemes(example) != example[::-1]
assert reverse_graphemes(reverse_graphemes(example)) == example

P.s. if you expect the brown hand pointing to the left to point to the right when reversed then all bets are off :smile:

3 Likes

@pf_moore that’s a bit of an oversimplification, don’t you think? Let’s be role play here! Suppose you’re pair programming with someone who maybe doesn’t know Python as well as you. How are you going to tell them to type [::-1]? “Open square bracket colon colon negative one close brackets”? Nevermind, it is kind of catchy with the right tune. :smiley: Bringing up the docs though… you’ll probably have to explain it to them yourself- you certainly won’t be able to point to a precise place in the docs for [::-1] like you would with a proper method. Where do you even find [] notation in the docs?


So maybe all the work needs to happen for the alternative slicing anyway?

@MegaIng and @Rosuav thanks for pointing that out. I did miss it. If you’re worried about the work, then don’t worry! Elixir can do it properly! Just copy them:

Interactive Elixir (1.18.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> example = "👈🏾👆"
"👈🏾👆"
iex(2)> String.reverse(example)
"👆👈🏾"

Might not be trivial, but why shy away from a problem?

@Lucas_Malor Yeah, that post got flagged for being too funny or something. Here is my use case:

@ntessore Why Ugh? I view it as exciting news!

@storchaka Turns out it won’t be simple as mentioned above, but we can copy Elixir for your example, too:

iex(3)> example = "🇺🇦"
"🇺🇦"
iex(4)> String.reverse(example)
"🇺🇦"

@Paddy3118 Thanks! I can stop referring to Elixir now :partying_face:

Edit: Sorry again for the novel, but got real busy with the kids and y’all posted a lot!

“Subscript with colon colon negative one”. I would assume that “subscript” is important enough to teach.

This is a programmer, not some generic voice dictation tool that has to have everything spelled out.

2 Likes

Sure, but is that really much better?

Notice how your request is now very different from “I want to use a name for [::-1] because I don’t like that” to “I want a method that does proper grapheme detection and reversing that”. So, which one is it? And are you, personally, willing to do the enormous amounts of work to implement the latter? (The former has close to 0 chance of being added. Dismissing arguments like you have been doing is not going to convince others)

2 Likes

I think this may be the feature you want to work on:

2 Likes

Which one is it? Let’s review the title of this post. Seems I want a method for reversing strings. I do not care how. In fact, what led me here was an attempt at implementing this myself, personally:

I don’t know C and was probably doing this wrong, but guess what? I was still willing to try to figure it out. I might need help and I might not be able to figure it all out myself, but I am not the one complaining about doing anything.

Edit: Thanks @petersuter !

Good, then start working on the issue above and be prepared to a few months to years of work, potentially including a PEP and maybe still never getting a str.reverse method (a unicodedata.reverse function is more plausible). I just want to make sure you understand the scope.

1 Like

The problem is that reversing a string is not really that useful and no good motivation has been given. Generally strings have a semantic that expects the ordering of the characters so that reversing them is meaningless. The unicode issues just seem like examples of this meaninglessness to me.

While it is apparently a popular stackoverflow question I imagine that is more because it is a common beginner exercise, interview question etc rather than something that is actually useful to do in practice. It is probably better to let those beginners learn about loops or slicing rather than giving them a ready made method.

Saying that sequences in general should have a .reverse() method rather than using slicing syntax would make more sense since in general it is useful to reverse a sequence. Of all the possible sequences that you might want to reverse strings seem like the worst choice of example to motivate this.

Having an algorithm to break strings into graphemes presumably has many reasonable applications that are not to do with reversing strings so that seems more like a well-motivated idea to me. It still might not be worth doing if it is particularly complicated though.

5 Likes