73240


アルゴリズムの学習をしていて、Pythonで文字列 `string` を反転させるメソッド `reverse` を作りたいです。

基本的な構文が分からず以下のコードでエラーが出てしまいます。正しいコードはどのように記述すればいいでしょうか？

**エラーメッセージ:**

[code]

    TypeError: 'str' object does not support item assignment
    
[/code]

**現状のコード:**

[code]

    def reverse(string, left, right):
        if left >= right: return
        t = string[left]
        string[left] = string[right] #Error
        string[right] = t #Error
        reverse(string, left + 1, right - 1)
    
[/code]


CC BY-SA 4.0
2021-01-12T04:02:23.943
73237
2021-01-14T10:34:05.787
2021-01-14T09:50:16.877
43413
43413
question
python python3
Pythonで再帰により文字列を反転させたい


文字列を配列のように取り出すことはできますが、一度代入された文字列変数はイミュータブル(変更不可能)なので配列のように部分的に変更することはできません。

文字列の一部を書き換えたい場合はスライスやリストを使って一部を書き換えた変数を再度代入する必要があります。  
[本家SOの類似回答](https://stackoverflow.com/a/22149018)

[code]

    #スライス
    s = 'abcde'
    s = s[:2] + 'o' + s[3:] #cをoに書き換え
    print(s) #abode
    
    #リスト
    l = list(s)
    l[1] = l[3] #bをdに書き換え
    s = "".join(l)
    print(s) #adode
    
[/code]


CC BY-SA 4.0
2021-01-12T04:46:57.000
73239
2021-01-12T04:46:57.000
9820
73237
answer


@payaneco さんの指摘に加えて、関数に戻り値を返す処理が記述されていないので、結果の確認やそれを次の何かに繋げることが出来ない状態です。

両方併せて対処するとすれば以下のようになるでしょう。

[code]

    def reverse(string, left, right):
        if left >= right: return string  #### 反転終了時の戻り値(string)を指定
        work = list(string) #### 以下は @payaneco さん指摘のリスト化して行う処理
        t = work[left]
        work[left] = work[right]
        work[right] = t
        return reverse(''.join(work), left + 1, right - 1)  #### 再帰呼び出しおよびそれ毎の戻り値
    
    result = reverse('abcdefghij', 0, 9)
    print(result)
    
    result2 = reverse('abcdefghij', 3, 6)
    print(result2)
    
[/code]


CC BY-SA 4.0
2021-01-12T05:13:08.197
73240
2021-01-12T05:13:08.197
26370
73237
answer


再帰実行の度に string → list → string へ変換するのは手間なのと、インデックス(`left`,
`right`)にマイナス値を使う事ができると良いかも知れません。

**reverse_string.py**

[code]

    def reverse(string, left, right):
      if  left < 0:  left += len(string)
      if right < 0: right += len(string)
      if left >= right: return ''.join(string)
      l = list(string) if isinstance(string, str) else string
      l[left], l[right] = l[right], l[left]
      return reverse(l, left + 1, right - 1)
    
    if __name__ == '__main__':
      string = 'Hello World!'
      print(reverse(string, 0, -1))
      print(reverse(string, 0, 4))
      print(reverse(string, 6, -2))
    
[/code]

[code]

    $ python3 reverse_string.py
    !dlroW olleH
    olleH World!
    Hello dlroW!
    
[/code]


CC BY-SA 4.0
2021-01-14T10:34:05.787
73294
2021-01-14T10:34:05.787
73237
answer