今さらPython3(9) - スライス大好き

引き続き、この本の2章を読んでます。

入門 Python 3

入門 Python 3

個人的にPythonで一番好きなのが[:]。スライスし放題なのがたまらなく好きです。(意味不明)

>>> letters = 'abcdefghijklmnopqrstuvwxyz'
>>> letters[0]
'a'
>>> letters[8]
'i'
>>> letters[-1]
'z'
>>> letters[25]
'z'
>>> letters[5]
'f'
>>> letters[100]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: string index out of range
>>>

ゼロから始まり、-1は後ろから1番目(一番後ろ)。収まらない数字を渡せば、そりゃ怒られるよねと。

>>> name = 'Henry'
>>> name[0] = 'P'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
>>> name.replace('H', 'P')
'Penry'
>>> 'P' + name[1:]
'Penry'
>>>
>>> name = 'P' + name[1:]
>>> name
'Penry' 

文字列はイミュータブルだよという説明のここ。これまで、あまりピンと来なかったのは、一番最後みたいな書き方すれば、結果的にnameという変数を変更できるからだったんだけど、最初のname[0]を上書きしようとして怒られてたのを見て、すっと腹落ちしました。

スライスで遊ぼう

>>> letters = 'abcdefghijklmnopqrstuvwxyz'
>>> letters[:]
'abcdefghijklmnopqrstuvwxyz'
>>> letters[20:]
'uvwxyz'
>>> letters[10:]
'klmnopqrstuvwxyz'
>>> letters[12:15]
'mno'
>>> letters[-3:]
'xyz'
>>> 

注意が必要なのは、下から2つめのletters[12:15]ぐらいかな?12文字目までオフセットして、13文字目から15文字目までを拾ってますと。

これは、本には載っていないけど、そもそも[:]というオプションを使う必要があるのかなというのを考えた時のもの。

>>> a = ''
>>> b = ''
>>> letters[a:b]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: slice indices must be integers or None or have an __index__ method
>>> a = None
>>> b = None
>>> letters[a:b]
'abcdefghijklmnopqrstuvwxyz'
>>> 

例えばプログラムの中で、文字列の中(この例ではletters)から任意の部分をスライスして取り出そうと考えた場合、print(letters[a:b])で出力するとして、aとbに値を入れて制御する事になるんだけど、結果的にaとbが空っぽだったら全部出力するみたいな感じで使えるかなと思ったり。その場合は、空白値('')じゃなくて、Noneを渡さないとダメのようです。

>>> letters[18:-3]
'stuvw'
>>> letters[-6:-2]
'uvwx'

範囲指定して、toの部分が-3, -2になっているのは、それぞれ後ろから3文字、2文字をオフセットしているよと理解すれば良さそう。

ステップとやら

スライスは好きだけど、正直あまり使ってこなかったステップの話。

>>> letters[::7]
'ahov'
>>> letters[4:20:3]
'ehknqt'
>>> letters[19::4]
'tx'
>>> letters[:21:5]
'afkpu'
>>> 

上から順に、

  • 最初から最後まで7つおき
  • オフセット4(実際には5番目から)20番目まで3つおき
  • オフセット19(実際には20番目から)4つおき
  • (先頭から)21番目まで5つおき

こんな感じ。ま、難しくない。つづいてステップが負の数だった場合。

>>> letters[-1::-1]
'zyxwvutsrqponmlkjihgfedcba'
>>> letters[::-1]
'zyxwvutsrqponmlkjihgfedcba'
>>> letters[4:20:-3]
''
>>> letters[::-3]
'zwtqnkheb'
>>> letters[0:25:-3]
''
>>> letters[:25:-3]
''
>>> letters[:-5:-3]
'zw'
>>> 

オフセット4から20番目の間でステップ-3みたいな意図で書いたのは、ブランク('')で返ってきちゃったのは意外。

>>> letters[20:4:-3]
'urolif'

じゃなくて、From-toも入れ替えてあげれば良いのね。それに気づいたのは、その後ろの部分を見たから。

>>> letters[-50:]
'abcdefghijklmnopqrstuvwxyz'
>>> letters[-51:50]
'abcdefghijklmnopqrstuvwxyz'
>>> letters[70:71]
''

(つづく)