関数の定義と使用
これまえ、スクリプトはシンプルで、コードブロックも一つの利用でした。Pythonコードを統一的にしてより読みやすく再利用しやすく作る方法の一つは、再利用の機能に使いやすいピースを要素ごとだすことです。ここで、関数を作る二つの方法を取り扱いましょう:def文はどんな型の関数にとっても使いやすいです、そして短い無名関数を作るのに役立つlambda文です。
関数の使用
関数は名前をもったコードのグループで、括弧を使って呼ばれます。前に関数をみています。例えば、Python3におけるprintは関数です。
In [1]:
print('abc')
abc
ここで、printは関数名です、そして、'abc'が関数の引数です。
引数に加えて、名前によって引数名が特定されます。一つの利用可能なprint()関数(Python3における)の引数キーワードはsepです、それは文字や文字列が複数の項目を分けるために使われるべきことを伝えるものです。
In [2]:
print(1, 2, 3)
1 2 3
In [3]:
print(1, 2, 3, sep='--')
1--2--3
キーワード引数なしでキーワード引数が一緒に使われるとき、キーワード引数は最後にこなければならないです。
関数の定義
複数の場所で使われるように機能的に統一すると、関数はそれ自体を定義し始めるときさえより使いやすくなりえます。Pythonでは、関数はdef文で定義されます。例えば、前の節からのフィボナッチの連続するコードのバージョンをかようにカプセル化できます:
In [4]:
def fibonacci(N):
L = []
a, b = 0, 1
while len(L) < N:
a, b = b, a + b
L.append(a)
return L
さて、Nという一つの引数をとるfibonacci という名前の関数をもてました。これはこの引数で何かをし値を返します。この場合、最初のNのフィボナッチ数のリストです。
In [5]:
fibonacci(10)
Out[5]:
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
もしあなたがCのような強い型言語になれているなら、すぐに関数の入力と出力で関連する型情報がないことに気づくでしょう。Pythonの関数は、単純であれ複合であれ、いかなるPythonのオブジェクトも返せます、それは他の言語では難しいかもしれない構成がPythonでは簡単であることを意味します。
例えば、複数の戻り値は単にタプルで出力されます、それはカンマによって示されます:
In [6]:
def real_imag_conj(val):
return val.real, val.imag, val.conjugate()
r, i, c = real_imag_conj(3 + 4j)
print(r, i, c)
3.0 4.0 (3-4j)
デフォルトの引数の値
しばしば関数を定義するとき、関数がたいていのときに使うようにしたい固定値がありますが、またいくつか柔軟性をユーザに与えたいです。この場合、引数に対するデフォルト値を使います。以前からのフィボナッチ関数を考慮しましょう。もし最初の値で実行することができるようにしたいならどうしますか?以下のようにできます:
In [7]:
def fibonacci(N, a=0, b=1):・
L = []
while len(L) < N:
a, b = b, a + b
L.append(a)
return L
一つの値で、関数呼出しの結果が前と比べて同じです。
In [8]:
fibonacci(10)
Out[8]:
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
しかし、いまや新しいことを探索するために、新しい最初の値の効果のように、関数を使えます。:
In [9]:
fibonacci(10, 0, 2)
Out[9]:
[2, 2, 4, 6, 10, 16, 26, 42, 68, 110]
値はまたお望みなら名前によって特定できます、この場合名前付けされた値の順番は問題にならないのです:
In [10]:
fibonacci(10, b=3, a=1)
Out[10]:
[3, 4, 7, 11, 18, 29, 47, 76, 123, 199]
*args と **kwargs: 柔軟な引数
ときどき、最初にパスする引数がどのくらい多いかわからないという点で、関数を書くことを望むかもしれない:この場合、パスされるすべての引数を捕捉するために argsとkwargsから特別なものを使うことができます。これは例です:
In [11]:
def catch_all(*args, **kwargs):
print("args =", args)
print("kwargs = ", kwargs)
In [12]:
catch_all(1, 2, 3, a=4, b=5)
args = (1, 2, 3)
kwargs = {'a': 4, 'b': 5}
In [13]:
catch_all('a', keyword=2)
args = ('a',)
kwargs = {'keyword': 2}
ここには、重要ではありますが名前付けされたargsとkwargsではなく、それらに先行する * 文字列があります。argsとkwargsは単に慣習的に使われる変数名で、"arguments"と"keyword arguments"の短縮です。操作の違いは、アスタリスク文字列です:変数の前の一つのアスタリスクは、"シーケンスとしてこれを広げよ"を意味し、変数の前の二つのアスタリスクは"辞書としてこれを広げよ"を意味します。事実、このシンタックスは関数定義だけでなく同じように関数呼び出しで使われます。
In [14]:
inputs = (1, 2, 3)
keywords = {'pi': 3.14}
catch_all(*inputs, **keywords)
args = (1, 2, 3)
kwargs = {'pi': 3.14}
無名関数(lambda)
前に簡単に関数定義でよく使われる def文の方法を見てみました。短い定義の他の方法を好んで用いるかもしれません、それはlambda文を使った一度限りの 関数です。こんな感じです:
In [15]:
add = lambda x, y: x + y
add(1, 2)
Out[15]:
3
このラムダ関数はおおざっぱには以下と同等です。
In [16]:
def add(x, y):
return x + y
なぜそんなものを今までに使っているのでしょうか?第一に、Pythonではすべてのものがオブジェクトだという事実に落ち着きます、関数自体さえ!それは関数が関数の引数としてパスされることを意味します。
この例として、辞書のリストに貯められるデータを持つとしましょう:
In [17]:
data = [{'first':'Guido', 'last':'Van Rossum', 'YOB':1956},
{'first':'Grace', 'last':'Hopper', 'YOB':1906},
{'first':'Alan', 'last':'Turing', 'YOB':1912}]
さて、このデータをソートしたいとするなら、Pythonはこれを行うソート関数を持ちます:
In [18]:
sorted([2,4,3,5,1,6])
Out[18]:
[1, 2, 3, 4, 5, 6]
しかし、辞書は順序付けできないです:どうやってデータをソートするかを関数に伝える必要があります。キーを関数として特定することによってこれができます、ある項目が与えられる関数はその項目のためのソートするキーを返します。
In [19]:
# sort alphabetically by first name
sorted(data, key=lambda item: item['first'])
Out[19]:
[{'YOB': 1912, 'first': 'Alan', 'last': 'Turing'},
{'YOB': 1906, 'first': 'Grace', 'last': 'Hopper'},
{'YOB': 1956, 'first': 'Guido', 'last': 'Van Rossum'}]
In [20]:
# sort by year of birth
sorted(data, key=lambda item: item['YOB'])
Out[20]:
[{'YOB': 1906, 'first': 'Grace', 'last': 'Hopper'},
{'YOB': 1912, 'first': 'Alan', 'last': 'Turing'},
{'YOB': 1956, 'first': 'Guido', 'last': 'Van Rossum'}]
これらのキー関数は普通のdefシンタックスによって確かに作ることができます、lambdaシンタックスはこのように短い一回限りの関数として慣習的なものです。