4-3. コンピュータにおけるファイルやディレクトリの配置¶
木構造のデータ形式について説明します。 この内容はPython言語に限らず、WindowsやMac、Linuxなどの一般的なOSにおいて共通する概念です。 Colaboratoryでは、同様の構造が仮想環境上に作られます。
みなさん、Windowsではエクスプローラ、MacではFinderを使ってファイルを階層的に保存していますよね。
下の例では、Windowsで ドキュメント
(Documents
) という名前のフォルダの中に Python入門
というフォルダを作り、 その下にこの教材を置いた時の、エクスプローラの様子を表しています。
これは Jupyter Notebook では以下のように見えます。
このようなデータ形式は以下のような図で表すこともできます。 まるで木を逆さにしたような形に見えますね。 ですからこのようなデータの形式を「木構造」と呼びます。
また、一番根っこにあたるデータを「ルート(根)」、先端にあたるデータを「リーフ(葉)」、その間にあるデータを「ノード(節)」と呼びます。
データの保存においては、ファイルはリーフ(葉)に相当し、フォルダはノード(節)に相当します。 ルートはハードディスクやUSBメモリなど記録媒体自体に対応することが多いです。 ハードディスクに入っているファイルと、USBメモリに入っているファイルは、それぞれ違う木に属するデータということです。
特にファイルの場所を意味するとき、フォルダのことをディレクトリと呼びます。
カレントワーキングディレクトリ¶
プログラムは、必ずどこかのディレクトリで動いています。 このプログラムが動作しているディレクトリのことを、ワーキングディレクトリ(もしくは作業ディレクトリ)と呼びます。 通例、特にWindowsやmacOSでは、何らかのファイルをクリックしてアプリケーションが起動したとき、その開いたファイルのある場所がワーキングディレクトリになります。
ワーキングディレクトリは、プログラムの実行中に変更できます。 Python上では os.chdir を使うことで変更できます。
プログラム実行中の現在のワーキングディレクトリのことを、カレントワーキングディレクトリ、もしくは単にカレントディレクトリと呼びます。 カレントディレクトリは頻繁に利用するので、 .
という特別な記号によって表現できます。 ## パス
カレントディレクトリに置かれているファイルは、ファイル名を指定するだけで開くことができます。 だから、4-1で示したように、カレントディレクトリにある sample.txt
は、ファイル名を指定するだけで開けます。
[1]:
open('sample.txt', 'r', encoding='utf-8')
[1]:
<_io.TextIOWrapper name='sample.txt' mode='r' encoding='utf-8'>
一方、それ以外の場所にあるファイルについては、そのファイルのディレクトリまで含めて指定しなければ、開くことができません。
[2]:
open('novel.txt', 'r')
---------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
Input In [2], in <module>
----> 1 open('novel.txt', 'r')
FileNotFoundError: [Errno 2] No such file or directory: 'novel.txt'
カレントディレクトリに存在しない novel.txt
を開こうとしたので FileNotFoundError
が生じました。 novel.txt
は、text
というディレクトリの中にあるので、それ明示するために、/
で区切って、次のように指定します。
[3]:
open('text/novel.txt', 'r', encoding='utf-8')
[3]:
<_io.TextIOWrapper name='text/novel.txt' mode='r' encoding='utf-8'>
実は、カレントディレクトリにあるファイルが、ファイル名の指定だけで開けるのは、自動的に ./
が補われていたからでした。
open
の第1引数に渡す文字列ような、ファイルやディレクトリの場所を指定する表記を、パスと呼びます。 パス(経路)と呼ぶのは、/
区切りで1歩ずつ次に進むディレクトリを指定することに由来しています。
パスを記述する際、ルートディレクトリは /
で表されます。 ルートディレクトリから始まるパスを、絶対パスと呼びます。 一方、カレントディレクトリからのパスを、相対パスと呼びます。 パス表記において /
以外から始まる場合は、自動的に先頭に ./
が補われて、相対パスとして扱われます。
さて、./text/
というパス表記は、カレントディレクトリにある一段下の text
ディレクトリに進むことに対応します。 これに、一段上のディレクトリを表す ..
を組み合わせることで、より柔軟にパスを指定できます。
たとえば、./text/../
は ./
と同じディレクトリを指します。
[4]:
with open('sample.txt', 'r', encoding='utf-8') as f:
print(f.read(), end='')
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
[5]:
with open('./text/../sample.txt', 'r', encoding='utf-8') as f:
print(f.read(), end='')
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
また、カレントディレクトリを ./text/
に変化させた後に、sample.txt
を開くときには、../sample.txt
と指定することができます。
[6]:
import os
os.chdir('./text') # 1段下の text に行く
with open('../sample.txt', 'r', encoding='utf-8') as f:
print(f.read())
os.chdir('..') # 元のディレクトリに戻る
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
木構造によるデータ表現¶
木構造はファイルやディレクトリの保存形式だけでなく、データの表現として幅広く利用されます。 たとえば家系図も木構造による表現です。「家系図」は英語で “family tree” ですよね。
このような構造を持つデータでは、まるで家系図のように、 上位下位関係にあるデータ同士を「親子 (parent/child)」と呼んだり、 同位関係にあるものを「兄妹 (sibling)」と呼んだりします。 「祖先 (ancestor)」や「子孫 (desendant)」という表現も使われます。
データのこのような表現は、実際に親子関係にあるかは関係ありません。 たとえば下の図は四肢動物の系統樹です。
データ構造的には、「有羊膜類」と「哺乳類」は親子関係にあるというわけです。
[ ]: