萬九郎の硬い船

プログラミング学習記録など

『退屈なことはPythonにやらせよう』10章 演習プロジェクト

10章の内容は「デバッグ」で、大いに勉強になった。演習プロジェクトは、バグを含むプログラムをデバッグするというもの。

入力させる値が'表'と'裏'なのに対してプログラム内部では'1'と'0'になっており、入力内容を判定できなくなっていたため、'表'と'裏'を'1'と'0'に直すようにした。また、入力させる部分を関数にして、2回目のトライの時もそれを呼び出すようにした。 次の章はいよいよ「スクレイピング」で、そもそもPyhonを習得する目的となったトピックなので愉しみだ。

『退屈なことはPythonにやらせよう』9章 演習プロジェクト

間が空いてしまった。9章の演習プロジェクトは1週間前にやっていたのだが、3つめの演習がすぐには解けずにそのまましばらく放置していた。 これではいかん。とにかく解けるものを解いて先に進みたいので、3つめは後で戻ってきて解くことにする。 1つめは「選択コピー」。

これはわりと簡単だった。 2つめは「巨大なファイルを探す」。

データ容量の閾値を指定できるようにしたのだが、バイト数で入力しないといけないのがダサい。できれば何メガとか何ギガとかで指定できるようにしたかった。 なお、9章で学んだ内容を踏まえて自分の日々の作業に使えそうなスクリプトを思いついたので、今度時間をとって書いてみようと思う。

『退屈なことはPythonにやらせよう』8章 演習プロジェクト

8章に入って、いよいよ扱うプログラムが実践的になってきた。学習したことを応用していろいろ作れそうだ。 8章の演習プロジェクトは3つあって、まずは本に載っている「マルチクリップボード」に削除機能を追加するもの。これは簡単だった。

第1コマンドライン引数が'delete'だった場合に第2コマンドラインのキーワードをクリップボード辞書から削除する。 第2コマンドライン引数が'–all'だった場合には辞書を全削除する。'all'の前にハイフンを2つ付ける仕様にしたのは、普段使用する他のコマンドでもオプションはハイフンを2つ付けるようになっていることが多いので、それに習った。ハイフン2つといえば、自分にとって最も身近なところではcssBEM記法で設計する際のelementとmodifierをつなぐのもハイフン2つだったりするが、こういう特殊な記法は見た目は悪いが合理的だ。今回の場合だと、'all'をクリップボード辞書のキーワードに使いたい場合が出てくるかもしれないが、全削除のオプションをハイフンなしの'all'にしてしまっているとそれができなくなる。

次に、「作文ジェネレータ」。

これは元のテキストのプレースホルダを'%(…)s'の形にしておいて、プログラム側では辞書形式を使って複数の変数で置き換えるようにした。

そして、最後は「正規表現検索」。

本に載っていないos.pathのメソッドを少し調べてみると

root, ext = os.path.splitext(file)

で拡張子を分離できることが分かったので、拡張子が'.txt'のファイルの場合のみ開く、という条件の部分に使ってみた(追記:これは'if file.endswith(‘.txt’):‘としても良いようだ)。 ファイルを横断して正規表現検索をする機能自体は普段使うテキストエディタに備わっているので、別にこのスクリプトを書いたからといって実際に使うかといえば使わないのだが、よく知った機能を自力で実装するのは勉強にはなった。

pyperclipを使ったクリップボード内のメアド検索:@が[at]などに置き換えられている場合について

『退屈なことはPythonにやらせよう』の7章に、クリップボード内のテキストから(電話番号や)メアドを検索して抜き出す方法というのが載っていた。 サイト上に載っているメアドはスパム避けのために@が[at]などに置き換えられていることも多いので、そういった場合に少しでもメアドを取りこぼさないプログラムにするために、練習がてら自分で改良を加えてみた。

import pyperclip, re

email_regex = re.compile(r'''(
    [a-zA-Z0-9._%+-]+  # ユーザー名
    (@|[[(_]+at[])_]+) # 隠蔽工作を含む@マーク
    [a-zA-Z0-9.-]+     # ドメイン名
    (\.[a-zA-Z]{2,4})  # ドット〜
)''', re.VERBOSE)

text = str(pyperclip.paste())
alt_atmark_regex = re.compile(r'[[(_]+at[])_]+')
matches = []

for groups in email_regex.findall(text):
    matches.append(alt_atmark_regex.sub('@', groups[0]))

if len(matches) > 0:
    pyperclip.copy('\n'.join(matches))
    print('クリップボードにコピーしました:')
    print('\n'.join(matches))
else:
    print('メールアドレスは見つかりませんでした。')

上記のうち、検索する際の正規表現

    (@|[[(_]+at[])_]+) # 隠蔽工作を含む@マーク

として、@が括弧やアンダーバーで「at」を囲んだもので置き換えられている場合もヒットするようにしたのと、 matchesリストに追加する際に

alt_atmark_regex = re.compile(r'[[(_]+at[])_]+')
matches = []

for groups in email_regex.findall(text):
    matches.append(alt_atmark_regex.sub('@', groups[0]))

として、括弧やアンダーバーで「at」を囲んだものを@に置き換え直すようにした。

『退屈なことはPythonにやらせよう』7章 演習プロジェクト

7章の演習プロジェクトは、正規表現を使った2つで、まずは「強いパスワードの検出」。

これは、最初にパスワードの強さテストを1項目ずつやっていく上のプログラムを書いた後でなんかこれだとダサいなと思い、少し調べた上で正規表現の「先読みアサーション」を使って下のプログラムに書き直した。「8文字以上かどうか」以外のテストをひとつにまとめたのだが、正規表現の書き方によっては全部1つのパターンで書けそうだ(現時点では知識およびスキル不足)。 課題では指示がないが、禁止文字までカバーできていないのが不満が残るところではある。

次に、「正規表現を用いたstrip()メソッド」。第1引数のテキスト文頭・文末にある空白文字を取り除き、第2引数がある場合は文頭・文末にあるその文字を取り除く。

これに関してはちょっと色々あった。まず、「*」のつく可変長引数はタプルになるため、中に入っている指定文字を取り出すために

character[0]

としてやる必要があり、さらにそれを正規表現に反映させるために

re.compile(r'^%s*' % character[0])

として正規表現内の%sを指定文字で置き換えている。 ちなみに、文頭パターンと文末パターンを別々に指定して別々に取り除いているが、これももっとスマートなやり方が全然ありそう。もうちょっと正規表現のgroupを活用できるようになった方がいい気がする。 勉強あるのみ。

『退屈なことはPythonにやらせよう』6章 演習プロジェクト

6章の演習プロジェクトは、リストを内包したリストを右揃えのテーブルとして表示させるプログラム。

右揃えの準備として、まず最初にリスト(外側)の長さぶんの0のリストを作り、その0をそれぞれ各リスト(内側)の最大長の値で置き換える。 これは本に載っていた通りにやっているが、他のプログラムを書くときにも使えそうな方法だと思った。

『退屈なことはPythonにやらせよう』5章 演習プロジェクト

5章の演習プロジェクトは、与えられた辞書形式のデータを「持ち物リスト」として表示するプログラムと、別のリストからその辞書にアイテムを移して辞書を更新するプログラム。

setdefault()メソッドは、第1引数で指定したキーが辞書に存在するかどうかを調べ、存在しない場合にはそのキーに第2引数に指定した値を設定する。