はじめに
この実験では、Python モジュールについて学びます。Python モジュールとは、他のプログラムでインポートして使用できる Python コードを含むファイルのことです。このモジュール化されたアプローチはコードの再利用を促進し、プログラムを論理的なコンポーネントに整理するのに役立ちます。
Python モジュールが何であるか、なぜ有用なのかを理解し、独自のモジュールを作成する方法を学び、さまざまな方法で import 文を使用する練習を行い、メインモジュールの概念とコードが実行されるタイミングを理解します。前提条件として、Python の構文と関数の基本的な理解、および Python スクリプトの作成と実行に慣れていることが必要です。この演習を開始する前に、クリーンな環境を得るために Python インタープリターのセッションを再起動することをお勧めします。
Python モジュールの理解
Python では、モジュールは Python の定義や文を格納するコンテナのようなものです。実質的にはファイルであり、このファイルの名前がモジュール名で、末尾に .py 拡張子が付きます。モジュールをツールボックスのように考えてください。モジュールは Python コードを論理的に整理するのに役立ち、再利用やメンテナンスを容易にします。整理を良くするために異なるツールを別々のボックスに入れるように、関連する Python コードを異なるモジュールにグループ化することができます。
この実験で設定されたファイルを見てみましょう。
- まず、エディタで
stock.pyファイルを開き、中身を確認します。これを行うには、以下のコマンドを使用します。cdコマンドはディレクトリをファイルがあるprojectフォルダに変更し、catコマンドはファイルの内容を表示します。
cd ~/project
cat stock.py
この stock.py ファイルは Stock クラスを定義しています。クラスはオブジェクトを作成するための青写真のようなものです。この場合、Stock クラスは株式を表します。株式の名前、株数、価格に関する属性(特性のようなもの)があります。また、株式のコストを計算するメソッド(クラスに関連付けられた関数のようなもの)もあります。
- 次に、
pcost.pyファイルを調べましょう。再びcatコマンドを使用してその内容を表示します。
cat pcost.py
このファイルは portfolio_cost() という関数を定義しています。関数は特定のタスクを実行するコードのブロックです。portfolio_cost() 関数はポートフォリオファイルを読み込み、そのポートフォリオに含まれるすべての株式の総コストを計算します。
- では、サンプルのポートフォリオデータを見てみましょう。
catコマンドを使用してportfolio.datファイルの内容を表示します。
cat portfolio.dat
このファイルには、簡単な形式で株式データが含まれています。各行には株式のティッカーシンボル、株数、1 株あたりの価格が記載されています。
import 文の使用
Python の import 文は、他のモジュールのコードを現在のプログラムで使用できるようにする強力なツールです。他のツールボックスからツールを借りるようなものです。コードをインポートするさまざまな方法を練習してみましょう。
- まず、Python インタープリターを起動する必要があります。Python インタープリターは Python コードを実行するプログラムです。以下のコマンドを使用して起動します。
python3
- では、
pcostモジュールをインポートして、何が起こるか見てみましょう。import文を使用すると、Python はpcost.pyファイルを探し、その中のコードを使用できるようにします。
import pcost
出力として 44671.15 が表示されるはずです。これは portfolio.dat ファイルから計算されたポートフォリオのコストです。pcost モジュールがインポートされると、pcost.py ファイルの末尾のコードが自動的に実行されます。
- 異なるポートフォリオファイルで
portfolio_cost()関数を呼び出してみましょう。pcost.portfolio_cost()構文を使用して、pcostモジュールから関数を呼び出します。
pcost.portfolio_cost('portfolio2.dat')
出力は 19908.75 であるはずで、これは 2 番目のポートフォリオファイルに含まれる株式の総コストを表しています。
- では、
stockモジュールから特定のクラスをインポートしてみましょう。モジュール全体をインポートする代わりに、from...import文を使用してStockクラスだけをインポートすることができます。
from stock import Stock
Stockクラスをインポートした後、Stockオブジェクトを作成することができます。オブジェクトはクラスのインスタンスです。名前がGOOG、株数が 100、価格が490.10のStockオブジェクトを作成します。そして、株式の名前を表示し、cost()メソッドを使用してそのコストを計算します。
s = Stock('GOOG', 100, 490.10)
print(s.name)
print(s.cost())
出力は以下のようになるはずです。
GOOG
49010.0
- 最後に、Python インタープリターの使用が終わったら、
exit()関数を使用して終了することができます。
exit()
この実験では、Python コードをインポートする 2 つの異なる方法を示しました。
import module_name- これはモジュール全体をインポートし、そのモジュール内のすべての関数、クラス、変数を使用できるようにします。from module_name import specific_item- これはモジュールから特定のアイテム(クラスや関数など)のみをインポートします。モジュールの機能の一部だけが必要な場合に便利です。
Python でのメインモジュールの理解
Python では、スクリプトを直接実行すると、それが「メイン」モジュールとして機能します。Python には __name__ という特別な変数があります。ファイルが直接実行されると、Python は __name__ の値を "__main__" に設定します。これは、ファイルがモジュールとしてインポートされる場合とは異なります。
この機能は非常に便利です。なぜなら、ファイルが直接実行されるか、インポートされるかに応じて異なる動作をするコードを書くことができるからです。たとえば、あるコードをスクリプトとしてファイルを実行したときにのみ実行し、他のスクリプトによってインポートされたときには実行しないようにしたい場合があります。
pcost.py をメインモジュールパターンを利用するように変更する
このパターンを利用するために、pcost.py プログラムを変更しましょう。
- まず、エディタで
pcost.pyファイルを開く必要があります。以下のコマンドを使用してプロジェクトディレクトリに移動し、ファイルが存在しない場合は作成することができます。
cd ~/project
touch pcost.py
cd コマンドは現在のディレクトリをホームディレクトリ内の project ディレクトリに変更します。touch コマンドは pcost.py という名前の新しいファイルが存在しない場合に作成します。
- 次に、
pcost.pyファイルを以下のように変更します。
## pcost.py
def portfolio_cost(filename):
total_cost = 0.0
with open(filename, 'r') as f:
for line in f:
fields = line.split()
try:
nshares = int(fields[1])
price = float(fields[2])
total_cost += nshares * price
except (ValueError, IndexError):
print(f"Couldn't parse: {line}")
return total_cost
## このコードはファイルがスクリプトとして実行されたときにのみ実行されます
if __name__ == "__main__":
total = portfolio_cost('portfolio.dat')
print(total)
主な変更点は、末尾のコードを if __name__ == "__main__": の条件文で囲んだことです。これは、このブロック内のコードがファイルがスクリプトとして直接実行されたときにのみ実行され、モジュールとしてインポートされたときには実行されないことを意味します。
- これらの変更を加えた後、ファイルを保存してエディタを終了します。
変更後のモジュールのテスト
では、変更後のモジュールを 2 つの異なる方法でテストし、その動作を確認しましょう。
- まず、以下のコマンドを使用してプログラムをスクリプトとして直接実行します。
python3 pcost.py
以前と同じように、出力として 44671.15 が表示されるはずです。これは、スクリプトを直接実行すると、__name__ 変数が "__main__" に設定されるため、if __name__ == "__main__": ブロック内のコードが実行されるからです。
- 次に、再び Python インタープリターを起動し、モジュールをインポートします。
python3
import pcost
今回は何も出力が表示されません。モジュールをインポートすると、__name__ 変数は "pcost"(モジュール名)に設定され、"__main__" ではなくなります。したがって、if __name__ == "__main__": ブロック内のコードは実行されません。
portfolio_cost関数がまだ機能していることを確認するには、以下のように呼び出すことができます。
pcost.portfolio_cost('portfolio.dat')
この関数は 44671.15 を返すはずで、これは関数が正常に動作していることを意味します。
- 最後に、以下のコマンドを使用して Python インタープリターを終了します。
exit()
このパターンは、インポート可能なモジュールとしても、スタンドアロンのスクリプトとしても使用できる Python ファイルを作成する際に非常に便利です。if __name__ == "__main__": ブロック内のコードは、ファイルが直接実行されたときにのみ実行され、モジュールとしてインポートされたときには実行されません。
独自のモジュールの作成
既存のモジュールの使い方がわかったところで、新しいモジュールをゼロから作成しましょう。Python のモジュールは、Python の定義や文を含むファイルです。これにより、コードを再利用可能で管理しやすいピースに整理することができます。独自のモジュールを作成することで、関連する関数や変数をまとめることができ、コードをよりモジュール化し、メンテナンスしやすくすることができます。
レポートモジュールの作成
株式レポートを生成するための簡単なモジュールを作成しましょう。このモジュールには、ポートフォリオファイルを読み込み、ポートフォリオ内の株式の整形されたレポートを印刷する関数が含まれます。
- まず、
report.pyという名前の新しいファイルを作成する必要があります。これを行うには、コマンドラインを使用します。ホームディレクトリ内のprojectディレクトリに移動し、touchコマンドを使用してファイルを作成します。
cd ~/project
touch report.py
- 次に、好みのテキストエディタで
report.pyファイルを開き、以下のコードを追加します。このコードは 2 つの関数とメインブロックを定義しています。
## report.py
def read_portfolio(filename):
"""
Read a stock portfolio file into a list of dictionaries with
keys: name, shares, price
"""
portfolio = []
with open(filename, 'r') as f:
for line in f:
fields = line.split()
try:
stock = {
'name': fields[0],
'shares': int(fields[1]),
'price': float(fields[2])
}
portfolio.append(stock)
except (ValueError, IndexError):
print(f"Couldn't parse: {line}")
return portfolio
def print_report(portfolio):
"""
Print a report showing the stock name, shares, price, and total value
"""
print("Name Shares Price Value")
print("-" * 40)
total_value = 0.0
for stock in portfolio:
value = stock['shares'] * stock['price']
total_value += value
print(f"{stock['name']:6s} {stock['shares']:9d} {stock['price']:9.2f} {value:9.2f}")
print("-" * 40)
print(f"Total Value: {total_value:16.2f}")
if __name__ == "__main__":
portfolio = read_portfolio('portfolio.dat')
print_report(portfolio)
read_portfolio 関数は、株式情報を含むファイルを読み込み、辞書のリストを返します。各辞書は、name、shares、price をキーとする株式を表します。print_report 関数は、ポートフォリオ(株式辞書のリスト)を受け取り、株式名、株数、価格、および総価値を示す整形されたレポートを印刷します。末尾のメインブロックは、ファイルが直接実行されたときに実行されます。ポートフォリオファイルを読み込み、レポートを印刷します。
- コードを追加した後、ファイルを保存してエディタを終了します。
モジュールのテスト
新しいモジュールが期待通りに動作することを確認するために、テストを行いましょう。
- まず、コマンドラインからスクリプトを直接実行します。これにより、
report.pyファイル内のメインブロックが実行されます。
python3 report.py
ポートフォリオ内の株式とその価値を示す整形されたレポートが表示されるはずです。このレポートには、株式名、株数、価格、総価値、およびポートフォリオ全体の総価値が含まれます。
Name Shares Price Value
----------------------------------------
AA 100 32.20 3220.00
IBM 50 91.10 4555.00
CAT 150 83.44 12516.00
MSFT 200 51.23 10246.00
GE 95 40.37 3835.15
MSFT 50 65.10 3255.00
IBM 100 70.44 7044.00
----------------------------------------
Total Value: 44671.15
- 次に、Python インタープリターからモジュールを使用します。ターミナルで
python3コマンドを実行して、Python インタープリターを起動します。
python3
インタープリターが起動したら、report モジュールをインポートし、その関数を使用することができます。
import report
portfolio = report.read_portfolio('portfolio.dat')
len(portfolio) ## Should return 7, the number of stocks
portfolio[0] ## First stock in the portfolio
import report 文により、report.py ファイルで定義された関数や変数が現在の Python セッションで使用可能になります。次に、read_portfolio 関数を使用してポートフォリオファイルを読み込み、結果を portfolio 変数に格納します。len(portfolio) 文はポートフォリオ内の株式の数を返し、portfolio[0] はポートフォリオ内の最初の株式を返します。
以下の出力が表示されるはずです。
7
{'name': 'AA', 'shares': 100, 'price': 32.2}
- では、インポートしたモジュールを使用して、自分でポートフォリオの総コストを計算しましょう。ポートフォリオ内の株式を繰り返し処理し、各株式の総価値を合計します。
total = 0.0
for stock in portfolio:
total += stock['shares'] * stock['price']
print(total)
出力は 44671.15 であるはずで、これは print_report 関数によって印刷される総価値と同じです。
- 最後に、特定の株式タイプに対するカスタムレポートを作成しましょう。ポートフォリオをフィルタリングして、IBM の株式のみを含め、
print_report関数を使用してそれらの株式のレポートを印刷します。
ibm_stocks = [stock for stock in portfolio if stock['name'] == 'IBM']
report.print_report(ibm_stocks)
これにより、IBM の株式とその価値のみを示すレポートが印刷されるはずです。
Name Shares Price Value
----------------------------------------
IBM 50 91.10 4555.00
IBM 100 70.44 7044.00
----------------------------------------
Total Value: 11599.00
- テストが終了したら、
exit()コマンドを実行して Python インタープリターを終了します。
exit()
これで、独自の Python モジュールを作成し、使用することに成功しました。関数と、ファイルが直接実行されたときにのみ実行されるメインブロックの両方を組み合わせています。このようなモジュール化されたプログラミングアプローチにより、コードを再利用し、プロジェクトをより整理された状態でメンテナンスしやすくすることができます。
まとめ
この実験では、Python モジュールの基本概念と、コードの整理にどのように利用するかを学びました。モジュールは再利用可能なコードを含む Python ファイルであり、import 文を使用することで、他のモジュールのコードを自分のプログラムで利用することができます。if __name__ == "__main__" パターンを使用すると、ファイルをインポート可能なモジュールとしても、スタンドアロンのスクリプトとしても機能させることができます。
これらの概念は、特に大規模なアプリケーションを開発する際に、メンテナンス可能な Python コードを書くために重要です。Python の学習を続ける際には、モジュールが関連するコードをまとめるのに役立ち、特定のアイテムをインポートすることで名前空間をきれいに保つことができ、メインモジュールパターンはベストプラクティスであることを覚えておいてください。これらの技術を適用することで、コードをより整理された状態で、メンテナンスしやすく、再利用可能にすることができます。