Python で関数オブジェクトを定義する際に def
コマンドを利用する。平均や分散などを計算する際に、NumPy や SciPy で用意されたメソッドを利用すればよいが、独自のアルゴリズムで計算したい場合などは、関数を一からつくり上げる必要がある。
基本的な作り方
関数は、def
に続いて関数名とコロンを書き、その次の行をインデントし、関数の処理を書く。例えば、2 つの引数(x
と y
)を受け取り、その差を返す関数は次のように作成する。ただし、関数は diff
とする。
def diff(x, y):
sa = x - y
return sa
自作した関数 diff
は以下のように利用する。
diff(30, 10)
## 20
dis(y = 10, x = 30)
## 20
関数を利用するにあたって、引数が足りないときにエラーが発生する。例えば、diff
関数の場合、2 つ目の引数 y
を省略すると、以下のようなエラーが発生する。
diff(30)
## Traceback (most recent call last):
## File "<stdin>", line 1, in <module>
## TypeError: diff() missing 1 required positional argument: 'y'
関数の引数に初期値を設定する方法
関数の引数に初期値を設定することができる。初期値が設定された関数が呼び出されると、引数が与えられていないは初期値を利用するようになる。例えば、次の関数では 、引数 x
が与えられていない場合は x = 30
として初期化を行い、引数 y
が与えられていない場合は y = 0
として初期化を行う。
def diff(x = 30, y = 0):
sa = x - y
return sa
diff(20)
## 20
diff()
## 30
複数個の値を返す方法
関数は 1 つの値をしか返せない。複数の値を返す必要がある場合、リストあるいはディクショナリにして返す。
def plus_and_minus(x, y):
a = x + y
b = x - y
c = [a, b]
return c
z = plus_and_minus(20, 10)
print(z)
## [30, 10]
また、次のように書くと、タプルとして返すようになる。
def plus_and_minus(x, y):
a = x + y
b = x - y
return a, b
z = plus_and_minus(20, 10)
print(z)
## (30, 10)
再帰処理
関数の中で、自分自身を呼び出すことを再帰呼び出しとよぶ。このような再帰的な処理を行う関数を再帰関数という。数学上、漸化式で表される問題を再帰関数で解くことができる。フィボナッチ数列がその代表例である。フィボナッチ数列は、0, 1, 1, 2, 3, 5, 8, ... のように、n 番目の値 f(n) は、n - 1 および n - 2 のときの値の和 f(n-1) + f(n-2) として表せる。
\[ f(n) = f(n-1) + f(n-2) \]n 番目のフィボナッチ数を求めるには、n - 1 と n - 2 番目の値がわかれば良いので、プログラムは、下のように書ける。
def fibo(n):
if n == 0 or n == 1:
s = n;
else:
s = fibo(n - 1) + fibo(n - 2)
return s
fibo(9)
## 34
参照渡し
Python は、関数にオブジェクトを代入するときに、基本的に参照渡しである。関数内部で、代入されたオブジェクトの値を書き換えると、その参照元のオブジェクトの値も書き換えられるため、十分に注意すること。ただし、整数や文字列などが代入されている immutable オブジェクトの場合は、関数内部でコピーが作られるので、値渡しとみなせる。
def add_M(x):
x.append('M')
return x
def add_N(x):
y = x
y.append('N')
return y
a = ['A', 'B', 'C']
print(a)
## ['A', 'B', 'C']
add_M(a)
print(a)
## ['A', 'B', 'C', 'M']
add_N(a)
print(a)
## ['A', 'B', 'C', 'M', 'N']
値渡し
関数の引数として渡されたオブジェクトが関数内で変更されても、その関数を抜けた時にその変更されないようなことにしたい場合、値渡しをする。ただし、Python では参照渡しが基本で、値渡しができない。そのため、関数の内部で、オブジェクトを受け取った後に、そのオブジェクトのコピーをとるなどの操作を行い、見かけ上の値渡しを行う必要がある。
import copy
def add_M(x):
y = copy.deepcopy(x)
y.append('M')
return y
def add_N(x):
y = copy.deepcopy(x)
z = y
z.append('N')
return z
a = ['A', 'B', 'C']
print(a)
## ['A', 'B', 'C']
b = add_M(a)
print(a)
## ['A', 'B', 'C']
print(b)
## ['A', 'B', 'C', 'M']
b = add_N(a)
print(a)
## ['A', 'B', 'C']
print(b)
##['A', 'B', 'C', 'N']