はじめに
このパートでは、Python スクリプトを書く実践について、もっと詳しく見ていきます。
このパートでは、Python スクリプトを書く実践について、もっと詳しく見ていきます。
「スクリプト」とは、一連の文を実行してから停止するプログラムのことです。
## program.py
statement1
statement2
statement3
...
これまで主にスクリプトを書いてきました。
便利なスクリプトを書くと、機能や機能性が増えていきます。他の関連する問題に適用したい場合もあるでしょう。時間が経つにつれて、重要なアプリケーションになるかもしれません。そして、注意を怠らなければ、巨大な混乱の山になってしまうかもしれません。ですから、整理をしましょう。
名前は、後で使用される前に必ず定義する必要があります。
def square(x):
return x*x
a = 42
b = a + 2 ## `a` が定義されていることが必要です
z = square(b) ## `square` と `b` が定義されていることが必要です
順序は重要です。 ほとんどの場合、変数や関数の定義を一番上に近付けます。
単一の「タスク」に関連するコードをすべて一箇所にまとめるのは良い考えです。関数を使いましょう。
def read_prices(filename):
prices = {}
with open(filename) as f:
f_csv = csv.reader(f)
for row in f_csv:
prices[row[0]] = float(row[1])
return prices
関数はまた、繰り返しの操作を簡略化します。
oldprices = read_prices('oldprices.csv')
newprices = read_prices('newprices.csv')
関数は、名前付きの文のシーケンスです。
def funcname(args):
statement
statement
...
return result
内部では、Python の「任意の」文を使用できます。
def foo():
import math
print(math.sqrt(2))
help(math)
Python には特別な文はありません(覚えやすいです)。
関数は、どんな順序でも「定義」できます。
def foo(x):
bar(x)
def bar(x):
statements
## または
def bar(x):
statements
def foo(x):
bar(x)
関数は、プログラム実行中に実際に「使用」(または呼び出し)される前にのみ定義する必要があります。
foo(3) ## foo は既に定義されている必要があります
スタイリッシュには、関数が「下から上」の形式で定義されるのが一般的です。
関数は構築ブロックとして扱われます。小さくて単純なブロックが先に来ます。
## myprogram.py
def foo(x):
...
def bar(x):
...
foo(x) ## 上で定義されています
...
def spam(x):
...
bar(x) ## 上で定義されています
...
spam(42) ## 関数を使用するコードは最後に現れます
後の関数は前の関数をベースに構築されます。再び、これはただのスタイルの問題です。上記のプログラムで重要なのは、spam(42) の呼び出しが最後に来ることだけです。
理想的には、関数は「ブラックボックス」であるべきです。関数は渡された入力のみで動作し、グローバル変数や不可解な副作用を避けるべきです。主な目標は、「モジュール性」と「予測可能性」です。
関数のドキュメント文字列を含めるのは良い慣例です。ドキュメント文字列は、関数名の直後に書かれる文字列です。これらは help()、統合開発環境(IDE)、その他のツールに提供されます。
def read_prices(filename):
'''
Read prices from a CSV file of name,price data
'''
prices = {}
with open(filename) as f:
f_csv = csv.reader(f)
for row in f_csv:
prices[row[0]] = float(row[1])
return prices
ドキュメント文字列の良い慣例としては、関数が何を行うかを 1 文で簡潔にまとめることです。もっと詳細な情報が必要な場合は、使用例の短いサンプルと引数のより詳細な説明を含めてください。
関数定義にオプショナルな型ヒントを追加することもできます。
def read_prices(filename: str) -> dict:
'''
Read prices from a CSV file of name,price data
'''
prices = {}
with open(filename) as f:
f_csv = csv.reader(f)
for row in f_csv:
prices[row[0]] = float(row[1])
return prices
これらのヒントは実際の動作には何も影響しません。純粋に情報提供のみを目的としています。ただし、統合開発環境(IDE)、コードチェッカー、その他のツールでは、これらのヒントを利用してさらに多くのことを行うことができます。
第 2 節では、株式ポートフォリオのパフォーマンスを示すレポートを出力する report.py というプログラムを作成しました。このプログラムはいくつかの関数で構成されていました。たとえば:
## report.py
import csv
def read_portfolio(filename):
'''
Read a stock portfolio file into a list of dictionaries with keys
name, shares, and price.
'''
portfolio = []
with open(filename) as f:
rows = csv.reader(f)
headers = next(rows)
for row in rows:
record = dict(zip(headers, row))
stock = {
'name' : record['name'],
'shares' : int(record['shares']),
'price' : float(record['price'])
}
portfolio.append(stock)
return portfolio
...
ただし、プログラムには一連の手順通りの計算のみを行う部分もありました。このコードはプログラムの後半に現れました。たとえば:
...
## Output the report
headers = ('Name', 'Shares', 'Price', 'Change')
print('%10s %10s %10s %10s' % headers)
print(('-' * 10 +'') * len(headers))
for row in report:
print('%10s %10d %10.2f %10.2f' % row)
...
この演習では、このプログラムを取り上げて、関数の使用を中心にもう少し強力に整理します。
report.py プログラムを変更して、計算や出力を含むすべての主要な操作を関数のコレクションによって行うようにします。具体的には:
print_report(report) 関数を作成します。プログラムの最後の部分を取り出して、単一の関数 portfolio_report(portfolio_filename, prices_filename) にまとめます。この関数は、次の関数呼び出しが以前と同じようにレポートを作成するように動作するようにします。
portfolio_report('/home/labex/project/portfolio.csv', '/home/labex/project/prices.csv')
この最終バージョンでは、プログラムは一連の関数定義の後に、最後に単一の関数呼び出し portfolio_report() だけになります(これがプログラムに含まれるすべてのステップを実行します)。
プログラムを単一の関数に変換することで、異なる入力で実行することが簡単になります。たとえば、プログラムを実行した後に対話的に次の文を試してみてください。
>>> portfolio_report('/home/labex/project/portfolio2.csv', '/home/labex/project/prices.csv')
... 出力を見る...
>>> files = ['/home/labex/project/portfolio.csv', '/home/labex/project/portfolio2.csv']
>>> for name in files:
print(f'{name:-^43s}')
portfolio_report(name, '/home/labex/project/prices.csv')
print()
... 出力を見る...
>>>
Python を使えば、文のシーケンスが記述された単一のファイルにすぎない比較的非構造化なスクリプトコードを書くことが非常に簡単です。全体的に見ると、できる限り関数を活用する方がほとんどの場合良いでしょう。いつかそのスクリプトが増えて、もう少し整理されていることを望むようになるでしょう。また、少々知られていない事実ですが、関数を使うと Python の実行速度が少し速くなります。
おめでとうございます!あなたはスクリプティングの実験を完了しました。あなたの技術を向上させるために、LabEx でさらに多くの実験を行って練習することができます。