見出し画像

【Python】SimplePrograms line 6 import してライブラリを使ってみようぜ


6行プログラムです。

コード

import re
for test_string in ['555-1212', 'ILL-EGAL']:
    if re.match(r'^\d{3}-\d{4}$', test_string):
        print (test_string, 'is a valid US local phone number')
    else:
        print (test_string, 'rejected')

実行結果

555-1212 is a valid US local phone number
ILL-EGAL rejected

解説

import です。
別のモジュールのコードにアクセスできます。
今回は「re(regular expressions:正規表現)」をインポートします。
正規表現は苦手です。
組み込みやってるとあまり使わないしね。

このプログラムが何をやっているのかは、 print 文を見ればある程度の想像がつきます。

is a valid US local phone number」とありますので、その文字列がアメリカの電話番号として妥当かどうかを確認しているわけです。

「3桁の数字ー4桁の数字」であればよいようです。

日本ならどうなるのかなぁ。
日本では、桁数そのものにも幾つか種類があるようだけど。
アメリカでも、実際はもっと複雑かもしれない。
これはあくまでサンプルなのかも。


ではまず、1行目。

import re

import の宣言です。
re」とはずいぶんシンプルなシンボルです。
マウスのない昔は短いシンボルが推奨されたものでした。
今でもITRONで「cre_tsk(create task)」などにその痕跡を見ることができます。

それにしても「re」とは、また思いきって略したものです。
それとも「re=正規表現」というのは一般的なんでしょうか。

とにかく。
この一文を書くことによって、正規表現に関するライブラリを使うことができるようになります。


2行目。

for test_string in ['555-1212', 'ILL-EGAL']:

確認する文字列を列挙しています。
と言っても2つだけですけれども。
555-1212」はOK。
ILL-EGAL」は数字ではないのでNG。


3行目。

    if re.match(r'^\d{3}-\d{4}$', test_string):

ここが要のチェックコードになります。
import した re のメンバ関数「match」を呼び出しています。
最初の引数「r'^\d{3}-\d{4}$'」が正規表現。
二番目の引数「test_string」がチェックする文字列。
test_string はリスト
 ['555-1212', 'ILL-EGAL']
から一つを取り出したものですね。
最初のループでは
 test_string = '555-1212'
二回目のループでは
 test_string = 'ILL-EGAL'
となります。
で、その文字列が正規表現
 「r'^\d{3}-\d{4}$'
にマッチするのかどうか。
では、この正規表現は何を意味するのでしょう。

ライブラリの解説はあまり本意ではないのですけど、まぁ、頑張りましょう。

と言いつつ、いきなり Python のドキュメントをコピーする。

\d
Unicode (str) パターンでは:
任意の Unicode 10 進数字 (Unicode 文字カテゴリ [Nd]) にマッチします。これは [0-9] とその他多数の数字を含みます。 ASCII フラグが使われているなら [0-9] のみにマッチします。
8 ビット (bytes) パターンでは:
任意の 10 進数字にマッチします。これは [0-9] と等価です。

https://docs.python.org/ja/3/library/re.html

「任意の Unicode 10 進数字」とはまた、幅が広い。
そんなことを言われるといろいろ試してみたくなるわけで。

「555-1212(全角)」だとどうなるのでしょう。

555-1212 is a valid US local phone number

おお!
すごいですね。
全角でも認識するんだ。

では「五五五-一二一二」。

五五五-一二一二 rejected

さすがに無理か。

いろいろ遊んでみる。

⑤⑤⑤-①②①② rejected
ⅤⅤⅤ-ⅠⅡⅠⅡ rejected
VVV-IIII rejected

ふむ。

ともかく。
「/d」は「一桁の数字」ということです。
では「{3}」は?

{m}
直前の正規表現をちょうど m 回繰り返したものにマッチさせるよう指定します。それより少ないマッチでは正規表現全体がマッチしません。例えば、 a{6} は 6 個ちょうどの 'a' 文字にマッチしますが、 5 個ではマッチしません。

https://docs.python.org/ja/3/library/re.html

そういうことですので、「\d{3}」は「一桁の数字3回」、すなわち「3桁の数字」ということになります。
すると「\d{3}-\d{4}」は「nnn-nnnn(nは数字)」ということですね。

では、「^」と「$」は?

^
(キャレット) 文字列の先頭にマッチし、 MULTILINE モードでは各改行の直後にもマッチします。

https://docs.python.org/ja/3/library/re.html

$
文字列の末尾、あるいは文字列の末尾の改行の直前にマッチし、 MULTILINE モードでは改行の前にもマッチします。 foo は 'foo' と 'foobar' の両方にマッチしますが、正規表現 foo$ は 'foo' だけにマッチします。興味深いことに、 'foo1\nfoo2\n' を foo.$ で検索した場合、通常は 'foo2' だけにマッチしますが、 MULTILINE モードでは 'foo1' にもマッチします。 $ だけで 'foo\n' を検索した場合、2 つの (空の) マッチを見つけます: 1つは改行の直前で、もう1つは文字列の末尾です。

https://docs.python.org/ja/3/library/re.html

^」は文字列の先頭にマッチした場合
$」は文字列の末尾にマッチした場合

要するに「^\d{3}-\d{4}$」は、
ぽっきり「nnn-nnnn(nは数字)」だけで、
前にも後にも何もつかない文字列であること。

そういうことになります。

そうしてそれを「' '」で囲みます。
それが
'^\d{3}-\d{4}$'
です。

残りは一文字。
r
これは
「バックスラッシュを特別扱いしない」
ということ。

"\n" が改行一文字
r"\n"'\''n' の二文字からなる文字列

なのだそうです。

すなわち、この if 文は
「test_string が nnn-nnnn(nは数字)というパターンにマッチしたとき」
という条件になります。


4行目。

       print (test_string, 'is a valid US local phone number')

これは
test_string

'is a valid US local phone number'
を空白でつなげて画面に出力するというだけです。

ちなみに、6行目も同じですね。

        print (test_string, 'reject')

test_string

'reject'
を空白でつなげて画面に出力するだけです。


最後、5行目。

    else:

else」文です。
3行目の「if」文に対応します。

if 文は
「test_string が nnn-nnnn(nは数字)というパターンにマッチしたとき
という条件でしたから、その else そうでなければという条件になります。

すなわち、
「test_string が nnn-nnnn(nは数字)というパターンにマッチしないとき
という条件になります。


間違いや改善方法、追加情報などありましたら、是非是非コメントくださいませ。


この記事が気に入ったらサポートをしてみませんか?