Python

【Python 8】関数

環境

macOS Big Sur
Python3.8

関数定義

「関数」とは、入力に対して特定の処理を実行し、出力を返す仕組みをいいます。「def文」を使用することで、関数を定義することができます。

関数の定義

def 関数名(引数1, 引数2, …):
    処理ブロック
    return 戻り値

関数名は変数と同じルールで作りますが、基本的にアルファベットは小文字のみを使用します。単語同士を合わせる場合はアンダースコア(_)で繋ぎます。

引数は処理ブロックで使用する変数であり、関数の呼び出し時に指定した値が代入されます。カンマ(,)で区切ることで、複数設定することも可能です(設定しないこともできます。)。

「return文」を使用することで、出力する値(「戻り値」)を指定することができます(return文は使用しなくても構いません。その場合、関数は「None」を返します。)。

なお、return文が呼び出された時点で関数の処理は終了します。同一関数内に複数のreturn文があったとしても、最初にreturn文が呼び出された時点で終了します。

関数は次のように呼び出します。

関数の呼び出し

関数名(引数1の値, 引数2の値, …)

>>> def mean(a):  # 関数meanを定義。
...     return sum(a)/len(a)
... 
>>> b = [1, 2, 3, 4, 5]
>>> mean(b)  # 関数meanの引数に変数bを渡して呼び出し。
3.0

 

関数定義の時に使用される引数を「仮引数」(parameter)、関数呼び出しの時に渡される引数を「実引数」(argument)といいます。

必須引数とデフォルト引数

引数には「必須引数」「デフォルト引数」があります。

必須引数は、関数の呼び出し時に省略できない引数をいいます。

デフォルト引数は、関数の呼び出し時に省略することもでき、省略した場合は「デフォルト値」が使用されます。

デフォルト引数を含む関数は次のように定義します。

必須引数とデフォルト引数の定義

def 関数名(引数1, 引数2=デフォルト値, …) :
    処理ブロック

※引数1が必須引数で、引数2がデフォルト引数です。関数呼び出し時に引数2を指定しなかった場合、引数2にはデフォルト値が自動的に代入されます。

※必須引数とデフォルト引数の両方を含む関数を定義する場合は、必須引数を先に定義し、その後にデフォルト引数を定義します。

def func(a, b=1):
    return a + b

# 必須引数aは必ず指定します。
# デフォルト引数bは指定しなければデフォルト値の1が代入されます。
# デフォルト引数bが指定された場合、指定された値が代入されます。
print(func(2))
print(func(2, 3))


# 実行結果
3
5

 

デフォルト値は、関数を定義した時点で判断されます。

また、デフォルト値の評価は一度しか行われません。

a = 1


def func(b=a):  # 引数bのデフォルト値は1です。
    return b


a = 2  # aを2で再定義。

print(a)
print(func())


# 実行結果
2
1

 

デフォルト値の引数への代入も参照渡しであり、関数を呼び出す度に、この引数は同じ場所を参照してしまいます。

そのため、デフォルト値がミュータブルの場合、参照先を変更してしまうとデフォルト値も変わってしまいます。

def func(a, b=[]):
    b.append(a)
    # appendはリストの末尾に要素を追加するメソッドです。
    # メソッドについては後述します。
    return b


print(func(1))  # デフォルト値の参照先の値は[]から[1]に変更されます。
print(func(2))  # デフォルト値の参照先の値は[1]から[1, 2]に変更されます。
print(func(3))


# 実行結果
[1]
[1, 2]
[1, 2, 3]

 

位置引数とキーワード引数

複数の引数を持つ関数を呼び出す際、引数は指定した順番通りに渡されます。この方式を「位置引数」といいます。

これに対して、どの引数にどの値を渡すかを「引数名=値」として指定することもできます。この方式を「キーワード引数」といいます。引数名を指定することで、順番を入れ替えても正しく引数を渡すことができます。

ただし、キーワード引数は順番を入れ替えるために使用されるのではなく、複数のデフォルト引数があり、そのうち1つだけデフォルト値以外を指定したい場合等に使用されます。

なお、キーワード指定した引数の後にキーワード指定しない引数を渡すことはできません。

辞書やタプルとして引数に渡す

仮引数を「**引数名」とすることで、キーワード引数を辞書として受け取ることができます。

また、「*引数名」とすることで、位置引数をタプルとして受け取ることができます。*引数名は**引数名の前に置きます。

必須引数、デフォルト引数、**引数、*引数が仮引数に混在する場合、以下の順番で定義する必要があります。

  1. 必須引数
  2. *引数
  3. デフォルト引数
  4. **引数
def func(a, *b, c=1, **d):
    print(a)
    print(b)
    print(c)
    print(d)


func(1, 2, 3, e=4, f=5)
# 初めの1はaに渡され、残りの位置引数2,3はbにタプルとして渡されます。
# デフォルト引数cに値を渡すには、キーワード引数として指定する必要があります。
# 仮引数にないe,fはdに辞書として渡されます。


# 実行結果
1
(2, 3)
1
{'e': 4, 'f': 5}

 

逆に、実引数を**引数名とすることで、辞書をキーワード引数として渡すことができ、*引数名とすることで、リストやタプルをアンパックして位置引数として渡すことができます。

def func(a, b, c, d, e, f=1):
    print(a)
    print(b)
    print(c)
    print(d)
    print(e)
    print(f)


g = [2, 3]
h = (4, 5)
i = {'e': 6, 'f':7}
func(*g, *h, **i)


# 実行結果
2
3
4
5
6
7

 

「*」や「**」を「unpacking operator」といいます。「*」はリストとタプルを「**」は辞書をアンパックします。

>>> a = (1, 2, 3)
>>> print(*a)
1 2 3

>>> b = {'one': 1, 'two': 2}
>>> c = {'three': 3, 'four': 4}
>>> {b, c}  # このような記法で結合はできません。
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'
>>> {**b, **c}  # 「**」でアンパックすることで、結合することができます。
{'one': 1, 'two': 2, 'three': 3, 'four': 4}

スコープ

変数や関数が所属する場所のことを「名前空間」といいます。名前空間は変数や関数が定義された場所によって決まります。

名前空間によって変数や関数が有効な範囲が決まります。この範囲を「スコープ」といいます。

変数が関数の外で定義されると、その変数はプログラムのどこからでも読み書きできます。この変数を「グローバル変数(モジュール変数)」といい、グローバル変数を参照できる範囲を「グローバルスコープ」といいます。

一方、関数の中で変数が定義されると、その変数は定義された関数の内部でしか読み書きできません。この変数を「ローカル変数」といい、ローカル変数を参照できる範囲を「ローカルスコープ」といいます。

グローバル変数とローカル変数は、たとえ同じ変数名だったとしても、別の変数として扱われます。そのため、関数内でグローバル変数に代入する際は、「global文」で明示的に指定する必要があります(global文で指定せずに代入すると、新規のローカル変数として定義されてしまいます。)。

なお、関数内であっても、print()関数等でグローバル変数を参照するだけなら、global文は不要です。

a = 1  # このaはグローバル変数です。


def func():
    a = 2  # このaはローカル変数です。
    return a


print(a)  # グローバル変数aが表示されます。
print(func())  # 関数func()を通してローカル変数aが表示されます。


# 実行結果
1
2

 

a = 1  # aはグローバル変数です。


def func1():
    global a  # global文で指定します。
    a += 2
    return a


def func2():
    return a  # 参照するだけならglobal文は不要です。


print(a)  # グローバル変数aが表示されます。
print(func1())  # グローバル変数aに2を加えた値が表示されます。
print(func2())  # グローバル変数aが表示されます。


# 実行結果
1
3
3

 

ドキュメンテーション文字列

関数定義の次の行(処理ブロックの先頭)に「docstring(ドキュメンテーション文字列)」というコメントを書き、関数の目的等の説明書きを加えることがあります。

docstringはインデント後、ダブルクォーテーション3つで囲います。

def func():
    """
    関数の目的(要約)を記載します。

    関数の呼び出し方や副作用(データの変更等によって生じる問題)等
    を記載します。
    """
    pass

 

アノテーション

関数定義の際に、引数や戻り値の型を明示する「注釈(アノテーション)」を入れることができます。この注釈を「Type annotation」「Type hint」といいます。

引数名の後に「コロン(:)」と「型名」を入れることで、引数の型を明示することができます。

また、ヘッダーのコロンの前に「->」と「型名」を入れることで、戻り値の型を明示することができます。

アノテーションを追記しても関数の処理内容に影響は出ません。

アノテーション

def 関数名(引数1: 型名, 引数2: 型名 = デフォルト値, …) -> 戻り値の型名:
    処理ブロック
    return 戻り値

def f(a: int, b: int = 2) -> int:
    return a + b

 

組み込み関数

Pythonに最初から用意されている関数のことを「組み込み関数」(Built-in Function)といいます。

組み込み関数については、公式ドキュメントを参照してください。

公式ドキュメント(組み込み関数)はこちら