Pythonで関数を定義する基本、位置引数やキーワード引数の渡し方と受け取り方、デフォルト引数値の指定、可変長引数の渡し方と受け取り方などを紹介する。
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
# パラメーターがなく、戻り値もない関数
def helloworld():
print('hello world')
helloworld() # hello world
# パラメーターがなく、戻り値がある関数
from datetime import datetime
def get_now():
return datetime.now().strftime('%Y/%m/%d %H:%M:%S')
result = get_now()
print(result) # 2022/05/04 15:21:42など
# パラメーターがあり、戻り値はない関数
def hello(whom):
print(f'Hello, {whom}')
hello('world') # Hello, world
# パラメーターと戻り値がある関数
def plus(x, y):
return x + y
result = plus(1, 2)
print(result) # 3
# 複数の値を返す関数
def multi_vals(x, y):
return x + y, x - y
result = multi_vals(1, 2)
print(result) # (3, -1)
total, diff = multi_vals(1, 2)
print(f'total: {total}, difference: {diff}') # total: 3, difference: -1
# 位置引数とキーワード引数
def pos_and_kwd(x, y):
print(f'x: {x}, y: {y}')
pos_and_kwd(1, 2) # 位置引数:x: 1, y: 2
pos_and_kwd(y=2, x=1) # キーワード引数:x: 1, y: 2
# デフォルト引数値の指定
def default_arg_value(x=1, y=2):
print(f'x: {x}, y: {y}')
default_arg_value() # x: 1, y: 2
詳細は以下の「関数定義の基本型」を参照のこと。
# 位置専用パラメーターの指定
def positional_only(a, b, /, c, d): # aとbにはキーワード引数として値を渡せない
print(f'a: {a}, b: {b}, c: {c}, d: {d}')
positional_only(1, 2, c=3, d=4) # OK: a: 1, b: 2, c: 3, d: 4
positional_only(a=1, b=2, c=3, d=4) # TypeError
# キーワード専用パラメーターの指定
def keyword_only(a, b, *, c, d): # cとdにはキーワード引数としてしか値を渡せない
print(f'a: {a}, b: {b}, c: {c}, d: {d}')
keyword_only(1, 2, c=3, d=4) # OK: a: 1, b: 2, c: 3, d: 4
keyword_only(1, 2, 3, 4) # TypeError
# 位置専用とキーワード専用の混在
def pos_and_kw(a, b, /, c, d, *, e, f): # cとdはどちらでもよい
print(f'a: {a}, b: {b}, c: {c}, d: {d}, e: {e}, f: {f}')
pos_and_kw(1, 2, 3, 4, f=6, e=5) # OK: a: 1, b: 2, c: 3, d: 4, e: 5, f: 6
pos_and_kw(1, 2, f=6, e=5, d=4, c=3) # OK
詳細は以下の「位置専用パラメーターとキーワード専用パラメーター」を参照のこと。
# 可変長位置パラメーター
def varpos(a, b, *args): # argsにはa、bが受け取ったもの以外が渡される(タプル)
print(f'a: {a}, {b}, args: {args}')
varpos(1, 2, 3, 4, 5) # a: 1, 2, args: (3, 4, 5)
varpos(1, 2, (3, 4, 5)) # a: 1, 2, args: ((3, 4, 5),)
lst = [1, 2, 3, 4, 5]
varpos(*lst) # a: 1, 2, args: (3, 4, 5)
# 可変長キーワードパラメーター
def varkwd(*, a, b, **kwargs):
print(f'a: {a}, b: {b}, kwargs: {kwargs}')
varkwd(b=2, a=1, d=4, c=3) # a: 1, b: 2, kwargs: {'d': 4, 'c': 3}
d = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
varkwd(**d) # a: 1, b: 2, kwargs: {'c': 3, 'd': 4}
# 可変長位置パラメーターと可変長キーワードパラメーターの混在
def varargs(a, b, *args, **kwargs):
print(f'a: {a}, b: {b}, args: {args}, kwargs{kwargs}')
varargs(1, 2, 3, d=4, e=5) # a: 1, b: 2, args: (3,), kwargs{'d': 4, 'e': 5}
詳細は以下の「可変長引数」を参照のこと。
関数はdef文を用いて定義する。
具体的にはキーワード「def」に続けて、関数名を記述し、その後にその関数の呼び出し時に渡される実引数を受け取るパラメーターをかっこ「()」で囲んで記述する。パラメーターが複数あるときにはカンマ「,」でそれらを区切る(並べられたパラメーターのことを「パラメーターリスト」と呼ぶこともある)。行末にはコロン「:」が必要なことに注意。
関数が実行する処理は、「def 関数名(パラメーターリスト):」行に続けて、インデントを付けて記述する(これを「関数本体」「関数ボディー」などと呼ぶことがある)。その関数が値を返す場合(これを「戻り値」「返り値」などと呼ぶ)、関数本体のどこかで「return 戻り値」を記述する。
def func_name(param1, param2, ……):
# 関数本体:関数が行う処理はインデントを付けて記述する
return_value = ……
return return_value # 関数が値を返す場合にはreturn文を記述する
以下はパラメーターも戻り値もないシンプルな関数の定義例だ。
def helloworld():
print('hello world')
helloworld() # hello world
return文を使って値を返さない関数(戻り値がない関数)でも、実際にはPythonのNone値が返されていることは覚えておこう。以下に例を示す。
result = helloworld()
print(result is None) # True:helloworld関数の戻り値はNone
パラメーターはないが、戻り値がある関数の例を以下に示す。
from datetime import datetime
def get_now():
return datetime.now().strftime('%Y/%m/%d %H:%M:%S')
result = get_now()
print(result) # 2022/05/04 15:21:42など
この例では、datetimeモジュールのdatetime.nowメソッドを呼び出して取得した現在の日時を「YYYY/MM/DD hh:mm:ss」形式に変換して返している。多くの関数はパラメーターに渡された値を基に何らかの処理を行い、その結果を返す(またはその結果を外部ファイルや標準出力に出力する)のだが、このようにパラメーターを持たずに、何らかの値を返す関数もある。
逆にパラメーターはあるが、戻り値がない関数も存在する。以下に例を示す。
def hello(whom):
print(f'Hello, {whom}')
hello('world') # Hello, world
この例では、hello関数はパラメーターwhomに受け取った値を使って、f文字列を組み立て、それをprint関数で画面に表示している。関数本体がprint関数呼び出しのみであり、print関数には戻り値がないことから、hello関数にも戻り値がないことになる。
パラメーターと戻り値の両方がある関数の例を以下に示す。
def plus(x, y):
return x + y
result = plus(1, 2)
print(result) # 3
この例では、パラメーターxとyに受け取った値を加算(文字列であれば結合)した結果が戻り値として返される。
Pythonの関数は複数の値を(タプルにまとめて)返すことも可能だ。これを行うには、return文で返したい値をカンマ「,」で区切って並べればよい。並べられた値はタプルを構成する要素となり、タプルが関数の戻り値となる。
以下に例を示す。
def multi_vals(x, y):
return x + y, x - y
result = multi_vals(1, 2)
print(result) # (3, -1)
total, diff = multi_vals(1, 2)
print(f'total: {total}, difference: {diff}') # total: 3, difference: -1
multi_vals関数のreturn文では、2つのパラメーターに受け取った値を加算した結果と減算した結果をカンマで並べているので、これら2つの値がタプルとして返される。そのため、最初の「result = multi_vals(1, 2)」という行では変数resultにタプルが代入される。そのため「print(result)」行では「(3, -1)」という2つの値を格納するタプルが表示される。タプルの値は、(タプルの要素数と代入文の左辺にある変数の数が等しければ)アンパック(分解)して代入できる。そのため、「total, diff = multi_vals(1, 2)」行では加算結果が変数totalに、減算結果が変数diffに個別に代入される。
関数呼び出し時に実引数の値をパラメーターに引き渡す方法として、「位置引数」と「キーワード引数」の2種類がある。位置引数を使用する場合、関数呼び出し時にかっこの中に引数を並べた順に、関数のパラメーターにそれらが渡される。
例えば、次のような関数があったとする。
def pos_and_kwd(x, y):
print(f'x: {x}, y: {y}')
位置引数を使ってpos_and_kwd関数を呼び出すには次のようにする。
pos_and_kwd(1, 2) # x: 1, y: 2
実引数(関数呼び出し時に指定する引数)は1、2の順に並べられているので、pos_and_kwd関数のパラメーターxとyにはその順に値が引き渡される。そのため、パラメーターxの値は1に、パラメーターyの値は2になる。
キーワード引数の代表的な渡し方としては、「パラメーター名=値」のようにして、どのパラメーターにどの値を渡すのかを指定する方法がある(この他に「{パラメーター名: 値}」のような辞書を用意して、それらを展開して渡す方法もある)。以下に例を示す。
pos_and_kwd(y=2, x=1) # x: 1, y: 2
この例では「y=2, x=1」のようにパラメーターxの値は1、パラメーターyの値は2と指定している。そのため、結果は「x: 1, y: 2」となる。
位置引数とキーワード引数を混在させて指定することも可能だ。以下に例を示す。
pos_and_kwd(1, y=2) # x: 1, y: 2
pos_and_kwd(y=2, 1) # SyntaxError
上の例の1つ目のpos_and_kwd関数呼び出しでは、「1」が位置引数、「y=2」がキーワード引数として関数に渡されている。このとき注意したいのは、2つ目の呼び出しのように、キーワード引数を先に指定することはできない点だ。位置引数は常にキーワード引数よりも前に指定する必要がある。関数定義中でのパラメーターの列挙時も同様な制約がある。
関数のパラメーターにそのデフォルト値を指定することも可能だ(これを「デフォルト引数値」などと呼ぶ)。デフォルト引数値を指定すると、関数呼び出し時にその引数の値の指定を省略でき、その場合、そのパラメーターの値はデフォルト引数値となる。多くの場合は決まった値を指定すればよいが、時にはそれとは異なる値を指定する必要が出てくるといった場合に、デフォルト引数値を用いることで、コードの記述をシンプルにできる。
デフォルト引数値を指定するにはパラメーターリスト中で「パラメーター名=デフォルト引数値」のようにする。
以下に例を示す。
def default_arg_value(x=1, y=2):
print(f'x: {x}, y: {y}')
default_arg_value() # x: 1, y: 2
この例では、パラメーターリスト中で「x=1, y=2」としているので、xの値を指定しなければその値は1に、yの値を指定しなければその値は2になる。関数定義の直下でしているように、引数なしでこの関数を呼び出すと、今述べた通りの値が2つのパラメーターに代入されているのが分かるはずだ。
デフォルト引数値を持つパラメーターは、持たないパラメーターよりもパラメーターリスト中で後ろに置かなければならないことには注意すること。例えば、以下の例ではデフォルト引数値を持つパラメーターが、持たないパラメーターよりも前にあるのでSyntaxErrorとなる。
def bad_param_list(a=1, b=2, c, d): # SyntaxError
pass
Copyright© Digital Advantage Corp. All Rights Reserved.