SimplePrograms - Python Wiki
https://wiki.python.org/moin/SimplePrograms
の 9番目のプログラムは、ファイルのオープン です。
# indent your Python code to put into an email
import glob
# glob supports Unix style pathname extensions
python_files = glob.glob('*.py')
for file_name in sorted(python_files):
print (' ------' + file_name)
with open(file_name) as f:
for line in f:
print (' ' + line.rstrip())
print()
9行じゃないですが、最初のコメント行は関係無いような気がするので無視してみます。
インポートする glob モジュールは、
「ディレクトリのワイルドカード検索からファイルのリストを生成するための関数を提供」
をするものです。bash でもお馴染みの 「*.txt」 とか、が使えるのですね。
glob の glob()メソッドは、この形式でファイル名を得ることができるはずで早速試してみます。
あるディレクトリ下で、prog-001.py と prog-002.py ファイルがあるとします。
$ ls
prog-001.py prog-002.py
$
そのディレクトリ下でpython3 を起動してみました。
>>> import glob
>>> glob.glob('*.py')
['prog-001.py', 'prog-002.py']
>>>
>>> glob.glob('*002*')
['prog-002.py']
>>>
各要素がパターンに合致するファイル名であるリストが得られますね。
リストが得られるということは、for文の sorted()は、引数のリストの各要素が文字列のものをソートしてくれそうです。
>>> sorted(['xyz','abc','dcb','dcc'])
['abc', 'dcb', 'dcc', 'xyz']
>>>
これで、python3 を実行中のディレクトリ下にあるパターンが合致するファイル名を python_files 変数にリストとして代入し、
for文で、それをソートして、一つづつ file_name に代入して、ループの中身を実行することが分かりました。
インデントされているループの中身を見てみましょう。
>>> print('aaaa' + 'bbbb')
aaaabbbb
>>>
なので、 文字列 + 文字列 は、文字列の連結ですね。
for ループの中の with は、with文ですね。
https://docs.python.org/ja/3/reference/compound_stmts.html#with
この解説は難しいので、チュートリアルを見ると、
「ファイルオブジェクトを扱うときに with キーワードを使うのは良い習慣です。 その利点は、処理中に例外が発生しても必ず最後にファイルをちゃんと閉じることです。」
要するに、with文を使ってファイルをオープンして、中身を読み込むのが目的で、as の後ろにあるファイルオブジェクト f が C言語で言うところのファイルポインタですね。
なぜこのようなものが必要かと言えば、複数ファイル同時オープン時に識別子として使うためのものでしょう。
しかも、with で open()すれば、close() ? を陽にしなくて良い?のが便利です。
Pythonでは read 文みたいなもの ( f.read() ) を使わなくても、for文でそのまま1行づつ読み込めて、
with open(ファイル名) as f:
for line in f:
読み込んだファイル内の1行 line に対する処理
と出来ると覚えておけば、今後の Python プログラミングで使えそうです。
https://docs.python.org/ja/3/library/stdtypes.html?highlight=rstrip#str.rstrip
から、line.rstrip()は、
「文字列の末尾部分を除去したコピーを返します。引数 chars は除去される文字集合を指定する文字列です。」
の chars が省略された場合で、行 line の後ろの空白文字が除去されるわけですね。
そこでわざと prog-002.py の1行目に長い空白文字を加えて見ます。
$ cat prog-002.py
#!/usr/bin/python3
name = input('What is your name?\n') #(分かりにくいですがここに空白文字)
print ('Hi, %s.' % name)
$
ちょっとうまく表示されそうにないので、 od コマンドで明確にしておきます。odの出力も相当乱れて表示されているので、実際に確認してみてください。
$ od -cx prog-002.py
0000000 # ! / u s r / b i n / p y t h o
2123 752f 7273 622f 6e69 702f 7479 6f68
0000020 n 3 \n n a m e = i n p u t (
336e 6e0a 6d61 2065 203d 6e69 7570 2874
0000040 ' W h a t i s y o u r n a
5727 6168 2074 7369 7920 756f 2072 616e
0000060 m e ? \ n ' )
656d 5c3f 276e 2029 2020 2020 2020 2020
0000100
2020 2020 2020 2020 2020 2020 2020 2020
*
0000220 \n
2020 2020 2020 2020 2020 2020 2020 0a20
0000240 p r i n t ( ' H i , % s . '
7270 6e69 2074 2728 6948 202c 7325 272e
0000260 % n a m e ) \n
2520 6e20 6d61 2965 000a
0000271
$
ここで、その上のディレクトリに、先頭に #!/usr/bin/python3 行を付加したこのプログラムの prog-009.py を作成し実行します。
$ ../prog-009.py
------prog-001.py
#!/usr/bin/python3
print ('Hello, world!')
------prog-002.py
#!/usr/bin/python3
name = input('What is your name?\n')
print ('Hi, %s.' % name)
$
プログラムの最後の print()で空行が表示されます。
念のため出力の該当部分を od 出力の抜粋で明らかにしておきます。
0000220 y o u r n a m e ? \ n ' ) \n
7920 756f 2072 616e 656d 5c3f 276e 0a29
0000240 p r i n t ( ' H i ,
for文の中にwith文、その中にfor文があるので、この辺のインデントの仕方は覚えておく必要がありますね。
ここまできて、だいぶ Python にもなれたので、そのまま続けたいと思います。
https://wiki.python.org/moin/SimplePrograms
の 9番目のプログラムは、ファイルのオープン です。
# indent your Python code to put into an email
import glob
# glob supports Unix style pathname extensions
python_files = glob.glob('*.py')
for file_name in sorted(python_files):
print (' ------' + file_name)
with open(file_name) as f:
for line in f:
print (' ' + line.rstrip())
print()
9行じゃないですが、最初のコメント行は関係無いような気がするので無視してみます。
インポートする glob モジュールは、
「ディレクトリのワイルドカード検索からファイルのリストを生成するための関数を提供」
をするものです。bash でもお馴染みの 「*.txt」 とか、が使えるのですね。
glob の glob()メソッドは、この形式でファイル名を得ることができるはずで早速試してみます。
あるディレクトリ下で、prog-001.py と prog-002.py ファイルがあるとします。
$ ls
prog-001.py prog-002.py
$
そのディレクトリ下でpython3 を起動してみました。
>>> import glob
>>> glob.glob('*.py')
['prog-001.py', 'prog-002.py']
>>>
>>> glob.glob('*002*')
['prog-002.py']
>>>
各要素がパターンに合致するファイル名であるリストが得られますね。
リストが得られるということは、for文の sorted()は、引数のリストの各要素が文字列のものをソートしてくれそうです。
>>> sorted(['xyz','abc','dcb','dcc'])
['abc', 'dcb', 'dcc', 'xyz']
>>>
これで、python3 を実行中のディレクトリ下にあるパターンが合致するファイル名を python_files 変数にリストとして代入し、
for文で、それをソートして、一つづつ file_name に代入して、ループの中身を実行することが分かりました。
インデントされているループの中身を見てみましょう。
>>> print('aaaa' + 'bbbb')
aaaabbbb
>>>
なので、 文字列 + 文字列 は、文字列の連結ですね。
for ループの中の with は、with文ですね。
https://docs.python.org/ja/3/reference/compound_stmts.html#with
この解説は難しいので、チュートリアルを見ると、
「ファイルオブジェクトを扱うときに with キーワードを使うのは良い習慣です。 その利点は、処理中に例外が発生しても必ず最後にファイルをちゃんと閉じることです。」
要するに、with文を使ってファイルをオープンして、中身を読み込むのが目的で、as の後ろにあるファイルオブジェクト f が C言語で言うところのファイルポインタですね。
なぜこのようなものが必要かと言えば、複数ファイル同時オープン時に識別子として使うためのものでしょう。
しかも、with で open()すれば、close() ? を陽にしなくて良い?のが便利です。
Pythonでは read 文みたいなもの ( f.read() ) を使わなくても、for文でそのまま1行づつ読み込めて、
with open(ファイル名) as f:
for line in f:
読み込んだファイル内の1行 line に対する処理
と出来ると覚えておけば、今後の Python プログラミングで使えそうです。
https://docs.python.org/ja/3/library/stdtypes.html?highlight=rstrip#str.rstrip
から、line.rstrip()は、
「文字列の末尾部分を除去したコピーを返します。引数 chars は除去される文字集合を指定する文字列です。」
の chars が省略された場合で、行 line の後ろの空白文字が除去されるわけですね。
そこでわざと prog-002.py の1行目に長い空白文字を加えて見ます。
$ cat prog-002.py
#!/usr/bin/python3
name = input('What is your name?\n') #(分かりにくいですがここに空白文字)
print ('Hi, %s.' % name)
$
ちょっとうまく表示されそうにないので、 od コマンドで明確にしておきます。odの出力も相当乱れて表示されているので、実際に確認してみてください。
$ od -cx prog-002.py
0000000 # ! / u s r / b i n / p y t h o
2123 752f 7273 622f 6e69 702f 7479 6f68
0000020 n 3 \n n a m e = i n p u t (
336e 6e0a 6d61 2065 203d 6e69 7570 2874
0000040 ' W h a t i s y o u r n a
5727 6168 2074 7369 7920 756f 2072 616e
0000060 m e ? \ n ' )
656d 5c3f 276e 2029 2020 2020 2020 2020
0000100
2020 2020 2020 2020 2020 2020 2020 2020
*
0000220 \n
2020 2020 2020 2020 2020 2020 2020 0a20
0000240 p r i n t ( ' H i , % s . '
7270 6e69 2074 2728 6948 202c 7325 272e
0000260 % n a m e ) \n
2520 6e20 6d61 2965 000a
0000271
$
ここで、その上のディレクトリに、先頭に #!/usr/bin/python3 行を付加したこのプログラムの prog-009.py を作成し実行します。
$ ../prog-009.py
------prog-001.py
#!/usr/bin/python3
print ('Hello, world!')
------prog-002.py
#!/usr/bin/python3
name = input('What is your name?\n')
print ('Hi, %s.' % name)
$
プログラムの最後の print()で空行が表示されます。
念のため出力の該当部分を od 出力の抜粋で明らかにしておきます。
0000220 y o u r n a m e ? \ n ' ) \n
7920 756f 2072 616e 656d 5c3f 276e 0a29
0000240 p r i n t ( ' H i ,
for文の中にwith文、その中にfor文があるので、この辺のインデントの仕方は覚えておく必要がありますね。
ここまできて、だいぶ Python にもなれたので、そのまま続けたいと思います。