Pythonの関数
関数とは
関数とは一連の処理をまとめたものです。1度宣言すると様々な場所からその関数を呼び出すことで処理を行うことができるようになります。
関数の使い方
関数であることを表したり、関数を呼び出したいことが理解できるように書き方にルールがあります。
関数の宣言
以下の構文で記述することで関数であることを表すことができます。
def 関数名():
処理
以下は実際のコードの例です。
def methodA():
print('methodAです')
関数の呼び出し
関数は以下の構文で呼び出すことができます。
関数名()
def methodA():
print('methodAです')
# methodAの処理が呼ばれる
methodA()
値を返す関数
関数は呼び出し元に値を返すことができます。値を返すときは以下の構文で返します
return 返したい値
以下はコードの例です。
def add():
return 1 + 1
print(f'1+1={add()}')
引数のある関数
引数というのはメソッドを実行するときに呼び出した関数が利用できる値のことです。
関数に引数がある場合、呼び出し元は基本的には引数を指定する必要があります。引数ありの関数を宣言するときは以下のように書きます。
def 関数名(変数名1,変数名2...変数名n)
先の「値を返す関数」の時に1+1の結果を返すプログラムを例にしました。実際には好きな数同士で足し算できた方が便利なはずです。これは引数を利用することで可能になります。
引数は値を指定できればよいので、変数で指定することも、直接値を指定することもできます。
def add(x,y)
return x + y;
x = 3
add(f'{x} + 7の結果は{add(x,7)}です')
異なるファイルの関数を呼ぶ
pythonでは異なるpythonファイルの処理を呼び出すことが可能です。フォルダが分かれている場合とそうでない場合で呼び出し方が変わります。
同じディレクトリにある場合
以下のようにprogramというディレクトリの中に呼び出したいpythonプログラムと呼び出し元のプログラムがある場合です。main.pyが実行するpythonプログラムでoutput_message.pyが呼び出されるプログラムです。
program
| output_message.py
| main.py
output-message.py
def outputSeparater():
print('-' * 50)
main.py
以下が異なるpythonファイルを呼び出すときの構文です。
import ファイル名
事前にこの記述をすることで関数を呼び出すことができます。以下はその例です。
import output_message
outputSeparater()
異なるディレクトリにある場合
以下のように異なるディレクトリにあるプログラムを呼び出したい場合です。
main.pyが実行されるpythonプログラムです。output_message.pyが呼び出したいpythonプログラムです。
program
| – messages
| | __init__.py
| | output_messages
| main.py
main.py
以下の構文で異なるディレクトリにあるプログラムを参照することができます。
form ディレクトリ名 import ファイル名
ディレクトリが2階層以上深い場合は以下のように「.」でつなげて記述することで呼び出せます。
form ディレクトリ名1.ディレクトリ名2 import ファイル名
from messages import output_message
outputSeparater()
__init__.py
messageディレクトリの下に__init__.pyがあることに気が付いたでしょうか?
異なるディレクトリのpythonプログラムを呼び出すためにはその親ディレクトリにこのファイルがなくてはなりません。
この__init__.pyはそのディレクトリにpythonプログラムがることを表すファイルです。このファイルを配置することで別のディレクトリからそのディレクトリのpythonプログラムを呼び出すことが可能になります。
この__init__.pyはそういう名前のファイルがあればよいので中身は何も書かなくてよいです。
関数化のメリット
プログラムを適切に関数化することで以下のメリットがあります。
- 処理を再利用することができる
- プログラムが読みやすくなる
- プログラムを変更しやすくなる
- テストやデバッグがしやすくなる
処理を再利用することができる
関数を宣言することでどこからでも、その処理を呼び出すことができます。
これにより同じ処理を何度も書く必要性がなくなります。
例として、ユーザが入力した数字を加算してその計算結果を出力するプログラムがあるとします。
出力結果を見やすくすることを目的として、プログラムの開始、ユーザーの入力が終わった後、計算結果を出力したあと、処理を終了した後に区切り線を出力しています。
print('----------')
print('処理を開始します')
x = input('数値を入力してください')
y = input('加算する数値を入力してください')
print('----------')
print(f'{x}+{y}の計算結果は{x + y}です')
print('----------')
print('処理を終了します')
print('----------')
この処理を書くときは線を出す処理が何度も書かれています。これを関数化すると以下のようになります。・・・区切り線を出力するときは一定の長さの-が出力れるようになりました。
def outputSeparater():
print('----------')
outputSeparater()
print('処理を開始します')
x = input('数値を入力してください')
y = input('加算する数値を入力してください')
outputSeparater()
print(f'{x}+{y}の計算結果は{x + y}です')
outputSeparater()
print('処理を終了します')
outputSeparater()
プログラムが読みやすくなる
プログラムを関数化することで処理を読みやすくする効果があります。
…例えば以下のようなプログラムがあったします。初心者でなくとも、何のプログラムを判断するのはすぐにはできないと思います。この処理の一部を関数化してみます。
formula = input('式を入力してください。(数字と式の間にはスペースを入れてください。)')
elements = formula.split(' ')
if not elements[0].replace('.', '', 1).isdigit():
print('式の先頭は数値にしてください')
exit()
addAndSub = []
addAndSub.append(elements.pop(0))
for element in elements:
match addAndSub[-1]:
case '*':
addAndSub.pop()
tmp = float(addAndSub.pop()) * float(element)
addAndSub.append(tmp)
case '/':
if element == '0':
print('0除算はできません。式を見直してください')
exit()
addAndSub.pop(-1)
tmp = float(addAndSub.pop()) / float(element)
addAndSub.append(tmp)
case _:
addAndSub.append(element)
result = float(addAndSub.pop(0))
for i in range(len(addAndSub))[::2]:
match addAndSub[i]:
case '+':
result += float(addAndSub[i+1])
case '-':
result -= float(addAndSub[i+1])
case _:
print('無効な演算子です。式を見直してください')
exit()
print(f'計算結果は{result}です。')
以下が処理を塊ごとに関数化したものです。関数化をすることで以下の順番で行っていることがわかりやすくなった…気がします。
- ユーザが入力した内容のチェック
- 掛け算と割り算を先に計算する
- 足し算と引き算を計算する
- 結果を出力する
def main():
formula = input('式を入力してください。(数字と式の間にはスペースを入れてください。)')
elements = formula.split(' ')
if not validInput(elements):
exit()
addAndSubFormula = calcMultiplicationAndDivision(elements)
result = calcAddAndsubtraction(addAndSubFormula)
print(f'計算結果は{result}です。')
def validInput(inputValue):
if not inputValue[0].replace('.', '', 1).isdigit():
print('式の先頭は数値にしてください')
return False
return True
def calcMultiplicationAndDivision(formula):
addAndSub = []
addAndSub.append(elements.pop(0))
for element in formula:
match addAndSub[-1]:
case '*':
addAndSub.pop()
tmp = float(addAndSub.pop()) * float(element)
addAndSub.append(tmp)
case '/':
if element == '0':
print('0除算はできません。式を見直してください')
exit()
addAndSub.pop(-1)
tmp = float(addAndSub.pop()) / float(element)
addAndSub.append(tmp)
case _:
addAndSub.append(element)
return addAndSub
def calcAddAndsubtraction(formula):
result = float(formula.pop(0))
for i in range(len(formula))[::2]:
match formula[i]:
case '+':
result += float(formula[i+1])
case '-':
result -= float(formula[i+1])
case _:
print('無効な演算子です。式を見直してください')
exit()
return result
if __name__ == "__main__":
main()
プログラムを変更しやすくなる
関数化することで変更が必要になったときに変更がしやすくなります。
再び、最初に示したサンプルを用意しました。
以下のプログラムの区切り線を変更したい場合、変更箇所がそれなりにあります。
print('----------')
print('処理を開始します')
x = input('数値を入力してください')
y = input('加算する数値を入力してください')
print('----------')
print(f'{x}+{y}の計算結果は{x + y}です')
print('----------')
print('処理を終了します')
print('----------')
しかし、先に示したように関数化しておくと1か所変更するだけで済みます。
def outputSeparater():
print('##########')
outputSeparater()
print('処理を開始します')
x = input('数値を入力してください')
y = input('加算する数値を入力してください')
outputSeparater()
print(f'{x}+{y}の計算結果は{x + y}です')
outputSeparater()
print('処理を終了します')
outputSeparater()
テストやデバッグがしやすくなる
プログラムに慣れてくるとデバッグをしたり、テストコードを書いてみたくなります。
関数化が上手くできているとテストやデバッグがやりやすくなります。
さいごに
プログラムの関数の使い方について解説しました。不明な箇所を調べたり、例となるプログラムを書いているうちに当初考えていたよりも長い記事になってしまいました。
慣れないうちは関数化をせずにどんどんプログラムを書いていくことでしょう。実際に書けるのですから最初の内はそれでもかまいません。ですが、プログラムを書くことに慣れて、もっと効率よく書きたいとかメンテナンスをどうしようかと考えたとき関数化を考えてみてください。