こんにちは。少し日が空いてしまいましたが、今日も頑張る。
○読んでいる本
以下の本を勉強がてら読んでいます。
ここにある通り、Pythonプログラムを改良する59項目が掲載されています。詳細は本に書かれているので、それを読めば良しとして、大事そうなところと、これに関連して勉強したことを書きます。
まとめページは以下より。
さて、今回は5つ目:「Know How to Slice Sequences」をやります。
○Know How to Slice Sequences
どうやってシーケンス(list, str, bytes)をスライスできるか知っておけというやつですね。
■スライス構文の基本形
スライスの基本形は、以下のような形で、startの要素が含まれ、endの要素が含まれません。
somelist[start:end]
マイナスとかもよく使うやつですね。
■リストの境界を超えた添え字も適切に扱われて便利
リストの境界を超えたあたいも、適切に表現されるので、かなり便利。
a = [1,2,3,4,5,6,7,8,9,10] print(a[:20]) print(a[-20:])
上のコードの出力は、どちらも、
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
になるという感じです。
これは入力シーケンスを考慮して最大長を設定したコードも簡単に書けるようになっています。
■代入するスライスの長さは同じでなくていい
これは「へぇー」ってなりました笑(えっ、もしかして常識?いや、こんなコード書くの?笑)
例えば、
a = [1,2,3,4,5,6,7,8,9,10] a[2:7] = ["a", "b", "c"] print(a)
とすると、出力は、
[1, 2, 'a', 'b', 'c', 8, 9, 10]
となるという笑。上の例は要素を減らしたパターンだが、要素を増やすパターンでやってみると、つまり、
a = [1,2,3,4,5,6,7,8,9,10] a[2:3] = ["a", "b", "c", "d", "e"] print(a)
とすると、
[1, 2, 'a', 'b', 'c', 'd', 'e', 4, 5, 6, 7, 8, 9, 10]
となるという笑。
■代入周りで覚えておきたいこと
これはほんまにいつもややこしいなぁ思う。笑
- スライスした結果は新しいリストが生成
- スライスせずに入れると元のリストのコピー
- コピー後、代入を行うと要素が入れ替わる
以下、それぞれ見ていく。
■スライスした結果は新しいリストが生成
スライス時は新しいリストが生成されるので、元の値を編集しても影響は出ない。つまり、
a = [1,2,3,4,5,6,7,8,9,10] b = a[4:] a[6] = "b" print(a) print(b)
とすると、以下のようになる(#以降はわかりやすさのために書いた)。
[1, 2, 3, 4, 5, 6, 'b', 8, 9, 10] # a [5, 6, 7, 8, 9, 10] # b
■スライスせずに入れると元のリストのコピー/コピー後、代入を行うと要素が入れ替わる
今度はスライスせずに入れると、元のリストのコピーになる。そのため、代入を何らかの方法で行うと要素が入れ替わることに注意。
これは、immutableかmutableかが問題で、リストはmutableなオブジェクトなので、このようなことが起きるんですね。この辺りは以下を参照。めちゃめちゃわかりやすいです。
対策は上のサイトでも書かれている通り、以下の三つでしのぐしかない。
- スライスを使う(例:copylist = somelist[:]):浅いコピー
- copyモジュールのdeepcopy()関数を使う(import copy, copylist = copy.deepcopy(somelist)):深いコピー
- for内包表記を使う:浅いコピー
浅いコピーの場合だと、以下のサイトで示されている通り、何もかもコピーするわけではなく、リストの中身が何かを参照している時、その参照先自体はコピーされないのです。
参考:Pythonの浅いコピー、深いコピー – HimaJew Blog
そのため、以下のような感じのことがおきます。
p=[1,2,3] q=[4,5,6] r=[7,8,9] A=[p,q,r] B=[x for x in A] A[0][0]="a" print(A) print(B)
上記のコードを実行すると、
[['a', 2, 3], [4, 5, 6], [7, 8, 9]] [['a', 2, 3], [4, 5, 6], [7, 8, 9]]
となりますので要注意ですね。
■pythonで文字列反転
よく使うのでメモ。リストでは、list[start:end:step]という感じなんだけどこれをうまく利用するとこうなるってやつ。
somestring[::-1]
参考:Python で文字列反転 - 似非プログラマの覚え書き
でも、これ次の項目でダメって言われているんご笑
○参考文献
リストのコピーについては、他にもたくさん参考文献が出ていたので、いくつか上げておく。