概要
「Head First Python 第2版」を進めていった中で考えたことの記録です。
Head First Python 第2版 ―頭とからだで覚えるPythonの基本
- 作者:Paul Barry
- 発売日: 2018/03/24
- メディア: 単行本(ソフトカバー)
サンプルコード
phrase = "Don't panic!" plist = list(phrase) print(phrase) print(plist) for i in range(4): plist.pop() plist.pop(0) plist.remove("'") plist.extend([plist.pop(), plist.pop()]) plist.insert(2, plist.pop(3)) new_phrase = ''.join(plist) print(plist) print(new_phrase)
最終的にどうなるのか
標準出力に以下の内容が表示されます。
Don't panic! ['D', 'o', 'n', "'", 't', ' ', 'p', 'a', 'n', 'i', 'c', '!'] ['o', 'n', ' ', 't', 'a', 'p'] on tap
内部的な動作は以下となります。
- 文字列
Don't panic!
を生成し、リストに変換する - 1.で生成された文字列の内容とリストの内容を標準出力に表示する
- 1.で生成されたリストに様々な操作を行い、文字列
on tap
が生成されるようなリストに作り替える - 3.の操作を行ったリストから、文字列
on tap
を生成する - 3.の操作を行ったリストの内容と4.で生成された文字列の内容を標準出力に表示する
このコードで行う処理を理解するにあたり、重要な事柄は以下と思われます。
Don't panic!
という文字列には、on tap
という文字列に必要な文字が全て含まれている
上記サンプルコードを実行して発生すること
初期状態を作る
phrase = "Don't panic!" plist = list(phrase) print(phrase) print(plist)
- 変数
phrase
に、文字列リテラル1Don't panic!
を代入する - 変数
phrase
の内容を元としてリストを生成し、生成されたリストを変数plist
に代入する- 生成されるのは、「変数
phrase
の1文字を1要素としたリスト」である
- 生成されるのは、「変数
- 変数
phrase
が指す内容を標準出力に表示する - 変数
plist
が指す内容を標準出力に表示する
この時点で、標準出力には以下の内容が表示されます。
Don't panic! ['D', 'o', 'n', "'", 't', ' ', 'p', 'a', 'n', 'i', 'c', '!']
末尾4文字は不要なので削除する
Don't panic!
という文字列のうち、末尾4文字のnic!
はon tap
という文字列に含まれません。文字列on tap
を生成するには不要な文字なので、plist
から除去してしまいます。
引数なしのpop()
をリストに対して実行すると、対象のリストの末尾1要素が除去されます。plist
に対してpop()
を4回実行すれば、末尾4要素が除去されるわけです。
Pythonにおいて「処理を4回繰り返し実行する」最もシンプルな方法は、「大きさ4の範囲を対象としてfor
文を実行する」というものですね。
結果、plist.pop()
を4回繰り返し実行するコードは以下になります。
for i in range(4): plist.pop()
実際にplist
に対してpop()
を4回実行すると、各回の結果は以下のようになります。
plist.pop() # plist => ['D', 'o', 'n', "'", 't', ' ', 'p', 'a', 'n', 'i', 'c'] plist.pop() # plist => ['D', 'o', 'n', "'", 't', ' ', 'p', 'a', 'n', 'i'] plist.pop() # plist => ['D', 'o', 'n', "'", 't', ' ', 'p', 'a', 'n'] plist.pop() # plist => ['D', 'o', 'n', "'", 't', ' ', 'p', 'a']
他の不要な文字を削除する
現時点のplist
から文字列を生成すると、結果は以下のようになります。
print(''.join(plist)) # => Don't pa
この時点では、文字列on tap
を生成するためにはD
・'
という不要な文字が残っています。この2文字をplist
から除去する必要があります。
最初の不要な文字であるD
は、plist
の先頭の要素として存在します。Pythonにおいて、リストの先頭の要素を指すインデックス番号は0
です。ということは、「plist
に対してpop(0)
を実行すれば、plist
からD
を取り除くことができる」ことになりますね。
# plist => ['D', 'o', 'n', "'", 't', ' ', 'p', 'a'] plist.pop(0) # plist => ['o', 'n', "'", 't', ' ', 'p', 'a']
もう一つの不要な文字である'
は、文字そのものを指定して取り除くこととしましょう。Pythonのリストにおいては、例えばx
という値を持つ最初の要素を取り除く場合、remove(x)
を実行すればOKです。"'"
という値であれば、remove("'")
を実行すればよいわけですね。
# plist => ['o', 'n', "'", 't', ' ', 'p', 'a'] plist.remove("'") # plist => ['o', 'n', 't', ' ', 'p', 'a']
必要な文字だけが残ったので、順番を入れ替える
現時点のplist
から文字列を生成すると、結果は以下のようになります。
print(''.join(plist)) # => ont pa
plist
にはon tap
という文字列を生成するために必要な文字だけが残っています。しかしながら、順番が一致していません。ont pa
をon tap
にするには、例えば以下の操作の組が必要となります。
- 現在4文字目にある空白文字を3文字目に移動する
ont pa
の4文字目にある空白文字を3文字目に移動すると、on tpa
になる
- 末尾2文字を入れ替える
on tpa
の末尾2文字を入れ替えると、on tap
になる
末尾2文字を入れ替える
同じリストに対し、引数なしのpop()
メソッドを2回実行すると、各pop()
メソッドの戻り値はそれぞれ以下となります。
- 1回目の
pop()
メソッドの戻り値…元のリスト末尾の要素の値 - 2回目の
pop()
メソッドの戻り値…元のリスト末尾から2つ目の要素の値
plist = ['o', 'n', 't', ' ', 'p', 'a'] print(plist.pop()) # => a print(plist.pop()) # => p # plist => ['o', 'n', 't', ' ']
「あるリストに対してpop()
メソッドを2回実行し、実行結果を順番に並べたリスト」を生成すると、その中身はどうなるのでしょうか。答えは、「元のリスト末尾から2つの要素を、元のリストにおける順番とは逆順に並べたリスト」となるのです。
plist = ['o', 'n', 't', ' ', 'p', 'a'] print([plist.pop(), plist.pop()]) # => ['a', 'p']
リストa
の末尾に新たな要素を追加するメソッドの一つに、a.extend(x)
メソッドがあります。a.extend(x)
メソッドには、「引数x
にリストを与えた場合、リストx
を構成する一つ一つの要素が順にリストa
の末尾に順番に追加される」という特徴2があります。
上記を踏まえると、「リストplist
の末尾2要素の順序を入れ替える」ためには、以下の処理を実行すればよい…ということになります。
# plist => ['o', 'n', 't', ' ', 'p', 'a'] plist.extend([plist.pop(), plist.pop()]) # plist => ['o', 'n', 't', ' ', 'a', 'p']
4文字目と3文字目を入れ替える
Pythonのリストには、以下の特徴があります。
- リストの
pop
メソッドを実行すると、その戻り値は「リストから除去された要素」となる - リストの
insert(i, x)
メソッドを実行すると、当該リストに新たな要素を挿入することができる- 新たな要素を挿入する位置は、インデックス
i
の直前 - 挿入される要素の内容は
x
- 新たな要素を挿入する位置は、インデックス
plist
から生成される文字列の4文字目と3文字目を入れ替えるには、「plist
の4番目の要素を除去し、その内容をplist
の3番目の要素の直前に挿入する」という操作を行えばよいということになります。Pythonのリストにおいて、インデックス番号は0
から始まるので、4番目の要素のインデックス番号は3
、3番目の要素のインデックス番号2
です。以上を踏まえると、現時点で必要な処理は以下となります。
plist.insert(2, plist.pop(3))
現時点のplist
に対し、実際に上記の処理を実行すると、その結果は以下のようになります。
# plist => ['o', 'n', 't', ' ', 'a', 'p'] plist.insert(2, plist.pop(3)) # plist => ['o', 'n', ' ', 't', 'a', 'p']
以上にて、plist
はon tap
という文字列を生成できる内容のリストとなりました。
文字列からリストを生成する
Pythonにおいて、文字列からリストを生成するためには、以下の関数を実行するのが最もシンプルと思われる方法です。
'*区切り文字列*'.join(x)
文字列のjoin(x)
メソッドですね。「引数x
で与えたリストの各要素を、*区切り文字列*
で指定した文字列を区切り文字列として連結した文字列を返す」という動作をします。*区切り文字列*
に空文字列を与えれば、引数x
で与えたリストの内容は、区切り文字なしで連結されることになります。
# plist => ['o', 'n', ' ', 't', 'a', 'p'] new_phrase = ''.join(plist) # new_phrase => 'on tap'
処理結果を標準出力に表示する
# plist => ['o', 'n', ' ', 't', 'a', 'p'] # new_phrase => 'on tap' print(plist) print(new_phrase)
内部的な動作は以下となります。
- 変数
plist
が指す内容を標準出力に表示する - 変数
new_phrase
が指す内容を標準出力に表示する
plist
およびnew_phrase
が上記の内容であれば、標準出力に表示される内容は以下となります。
['o', 'n', ' ', 't', 'a', 'p'] on tap
以上で、サンプルコード全体の説明が終わりました。