関数の定義と呼び出し

関数の定義と呼び出し

関数の定義と呼び出し

 この記事では Python における 関数 (funciton) について解説します。一般的な説明に入る前に、関数を使った簡単なサンプルコードを書いておきます。

# PYTHON_FUNCTION_01

# In[1]

# 三角形の面積を計算する関数を定義します
# base:底辺の長さ、height:高さ
def triangle_area(base, height):
    return base * height / 2

# 底辺の長さが 10, 高さ 15 の三角形の面積を計算します
s = triangle_area(10, 15)

print(s)
# 75.0

 上のコードでは def キーワードを使って、triangle_area という名前の関数を定義しています。triangle_area() は、base(底辺)と height(高さ)が指定されると、
 
  base (底辺) × height (高さ) / 2
 
によって三角形の面積を計算し、return キーワードでその値を返すように設計されています。そして、base に 10, height に 15 を指定して、
 
  s = triangle_area(10,15)
 
と記述することによって、triangle_area関数を呼びだして、底辺 10、高さ 15 の三角形の面積を求めて、その値を変数 s に格納しています。
 
 このように、プログラムの中で入力値を受け取って命令を実行し、出力値を返す機能を 関数 (funciton) とよびます。
 
Python関数 出力と入力モデル
 
 Python では関数を次のような記述で定義します。

def 関数名(引数1, 引数2, ...):
    関数ブロック

 関数名は変数と同じく、Python の予約語などの一部の例外を除けば好きなように決められます。ただし「大文字は使わない」、「単語の区切りはアンダースコアにする」などの Python エンジニアとしての慣習は守ったほうがいいでしょう。
 
 丸括弧の中には関数に渡す引数名を書きます。引数の数は関数ブロックで処理する内容によります。引数が1つだけの場合もあれば、複数の場合もあります。あるいは引数がない関数も存在します。

 丸括弧のあとにはコロンを付けて改行し、半角スペース 4 つでインデントします。
 その後ろの関数ブロックに「受け取った引数をどのように処理するか」ということを書きます。多くの関数は return キーワードによって何を出力するか定義します。この出力のことを 戻り値 といいます。戻り値は数値や文字列といった単純なものばかりでなく、リストやタプルのようなイテラブルオブジェクトである場合もあります。また一部には戻り値のない関数も存在します。
 
 関数を呼びだすときは

関数名(引数1, 引数2, ...)

と記述するだけです。引数のない関数をよびだすときでも、関数名のあとに () は必ず添えておきます。
 
 関数の定義に return 文が必須というわけではありません。関数ブロックに return の記述がない場合、その関数の戻り値は None となります。

# In[2]

def func(x):
    x ** 2

print(func(2))
# None

 return がなくても、関数ブロックの中で print() 関数を使うことで、処理結果を表示させることができます。

# In[2]

def my_message():
    print("Python最高!")

my_message()
# Python最高!

 
 関数の引数には数値だけでなく、リストタプル のような シーケンス を渡すことができます。ここでは2つのシーケンスの要素同士を加える関数を定義してみます。要素が数値であれば、数学の 2 次元ベクトル同士の加算となるので、vector-addition を略して vec_add という関数名にしてあります。

# In[3]

# 要素同士を加える関数
def vec_add(x, y):
    return (x[0] + y[0], x[1] + y[1])

# ベクトルの加算
# 引数をタプルで指定
v = vec_add((0,1),(2,3))

# 文字列の連結
# 引数をリストで指定
w = vec_add(["a", "b"],["c", "d"])

print("v:{}".format(v))
print("w:{}".format(w))
# v:(2, 4)
# w:('ac', 'bd')

 変数 v にはベクトル演算 (0, 1) + (2, 3) の結果を入れています。変数 w には同じインデックスをもつ要素同士の文字を連結しています。

必須引数とオプション引数

 次のサンプルコードでは 1 次関数を定義してみます。
 ユーザーは変数 x と係数 a, b を入力して、1 次式の計算結果を受け取ります。

# PYTHON_FUNCTION_02

# In[1]

# 1 次関数を定義
# x は必須引数、a, b はオプション引数
def linear_func(x, a = 1, b = 0):
    return a * x + b

# x = 2 を指定
# a, b はデフォルト値 (a = 1, b = 0)
f1 = linear_func(2)

# x = 3, a = 5, b = 11 を指定
f2 = linear_func(3, 5, 11)

print("f1:{0}, f2:{1}".format(f1, f2))
# f1:2 , f2:26

 3 つの引数のうち、x は 必須引数、a と b は オプション引数 とよばれます。必須引数は必ず指定しなければならない引数ですが、オプション引数は省略することができます。オプション引数は

関数名 ([引数名] = [引数値])

のように記述しておきます。関数が呼び出されるときにオプション引数が省略された場合には、[引数値] がデフォルト値として関数に渡されて計算されることになります。
 
 上のサンプルコードにおいて、f1 は必須引数 x のみ指定しているので、a に 1, b に 0 が渡されて計算が実行されます。f2 についてはすべての引数が指定されているので、デフォルト値は使用されません。

キーワード引数

 linear_func関数には x, a, b という3つの引数があります。オプション引数のうち a は省略して b だけを指定したいという状況もありえます。そのような時には「キーワード = 引数」という形で指定引数を明示します。キーワードというのは、関数を定義するときに決めた引数名のことです。

# PYTHON_FUNCTION_03

# In[1]

# 1 次関数を定義
# x は必須引数、 a, b はオプション引数
def linear_func(x, a = 1, b = 0):
    return a * x + b

# a を省略して b をキーワードで指定
y = linear_func(10, b = 8)

print(y)
# 18

 オプション引数だけでなく、必須引数もキーワードで指定することもできます。キーワードで指定された引数は互いに順番を変えてもかまいません。特に順番を変える必要もないし、混乱の原因になるので、そのような記述の仕方はなるべく避けるべきですが、あくまで動作確認用にサンプルコードを載せておきます。

# In[2]

# 引数 b, x をキーワードで指定
y = linear_func(b = 9, x = 11)

print(y)
# 20

可変引数

 関数の引数の前にアスタリスク (*) を1つ添えると、可変引数として扱われ、キーワード指定しない引数をいくつでも受け取ることができるようになります。可変引数はタプル形式で格納されます。

# PYTHON_FUNCTION_04

# In[1]

# 指定された引数をタプルで返す関数の定義
# param は parameter の略
def param_show(*vals):
    return(vals)

x = param_show("a", "b", "c", "d", "e")

print(x)
# ('a', 'b', 'c', 'd', 'e')

 上のサンプルで定義した param_show関数は 10 個でも 20 個でも引数を受け取ることができて、それらをすべてタプルに入れて返してきます。ただし、これらの引数はすべて未定義引数として扱われるので、次のように vals をキーワードに指定して関数を呼びだそうとしても TypeError が発生します。

# In[2]

x = param_show(vals = 1)

print(x)
TypeError
 Traceback (most recent call last)
  in ()
      3     return(vals)
      4 
 ----> 5 x = param_show(vals=1)
      6 
      7 print(x)

 TypeError: param_show() got an unexpected keyword argument 'vals'

 最後の行で「 param_show関数は予期しない引数 'vals' を受け取った」という警告文が表示されています。
 
 引数の前にアスタリスク (*) を2つ添えると、可変引数として扱われ、キーワード指定された未定義の引数をいくつでも受け取ることができるようになります。渡された引数はキーワードを key、引数を値とするディクショナリに格納されます。

# In[3]

# 指定された引数をディクショナリで返す関数の定義
def param_show(**vals):
    return(vals)

x = param_show(p = 1, q = 2, r = 3)

print(x)
# {'p': 1, 'q': 2, 'r': 3}

Python の組み込み関数

 Python 本体にはあらかじめ用意されている関数があって、外部からのインポートなしで、いつでも使うことができるようになっています。このような関数を 組み込み関数 とよびます。たとえばオブジェクトの長さを取得する len() という関数があります。len 関数は引数に文字列を指定すると文字数を、リストのようなシーケンス型を指定すると要素数を返します。

# PYTHON_BUILT_IN_FUNCTION

# In[1]

my_str = "Python でラプラス変換する方法を調べています"
my_list = ["古典力学", "解析力学", "量子力学"]

# 文字数を取得します
s = len(my_str)

# 要素の数を取得します
t = len(my_list)

print(s, " ", t)
# 25 3

 他にも数学で多用する絶対値を返す abs() という関数が用意されています。

# In[2]

# -100 の絶対値を取得します
x = abs(-100)

print(x)
# 100

 シーケンス の要素を合計するときは sum() 関数を使います。

# In[3]

# 初項 2, 公差 3 の等差数列のリスト
a_seq = [2, 5, 8, 11, 14, 17, 20, 23, 26]

# 等差数列の和を求めます
s_a_seq = sum(a_seq)

print(s_a_seq)
# 126