『Python数値計算ノート』ではアフィリエイトプログラムを利用して商品を紹介しています。

関数の定義と呼び出し

関数の定義と呼び出し

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

# 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

コメント

  1. k_gawa より:

    はじめまして、大学院生をしているものです。
    こちらのサイトで1からpythonと数値計算について学ばせていただいております。
    体系的に学習でき、大変勉強になっております。ありがとうございます。

    # PYTHON_FUNCTION_05 codeですが、
    print(“f1 = {1}, f2 = {2}”.format(f1, f2))
    は正しくは、
    print(“f1 = {0}, f2 = {1}”.format(f1, f2))
    でしょうか? よろしくお願いいたします。
    k_gawa

    • BlogCat より:

      当サイトを活用していただけると、私も嬉しいです。
      御指摘の通り、正しくは
      print(“f1 = {0}, f2 = {1}”.format(f1, f2))
      です。さきほど記事は修正しておきました。
      1人ですべての記事をチェックできないので、ミスを指摘いただけると本当に助かります。
      ありがとうございました。今後もよろしくお願いします。

      • k_gawa より:

        ご返信ありがとうございます。
        かなりおせっかいなことをしてしまったと反省しておりましたが、そう言っていただけると幸いです。
        こちらこそよろしくお願いいたします。
        k_gawa

  2. datsu より:

    関数型プログラミングに興味がわきましたが、学習した経験がPythonしかなかったので探した結果、たどり着きました。
    他の言語にも興味がわきましたが、慣れたPythonで考え方を学べたのはよかったです。ありがとうございました。
    プログラムの組み立て方がまだ理解できていませんが、参考にさせていただきます。

    • あとりえこばと より:

      コメントありがとうございます。
      Pythonは手続き型、関数型、オブジェクト指向など複数の手法を取り込んだ「マルチパラダイム言語」なので、Pythonを学んだことは他の言語を習得するときにも役立つはずです。将来的に関数型寄りの言語を学ぶのであれば、高階関数、イテレータ、クロージャなどについて理解を深めておくと良いと思います。ぜひ頑張ってください!