1. ホーム 
  2. 備忘録 
  3. Python

関数

関数について

Python ではプログラムを上から順に読み込むため、関数の呼び出しは関数の定義を先に済ませてから行わなければいけない

関数の定義について以下に例を記載する


#------------------------------------------------
### 返り値なし関数
def say_something():
    print('hi')


# 関数名で呼び出し
say_something()  # hi

# 変数に格納して呼び出し
print(type(say_something))  # <class 'function'>
f = say_something
f()  # hi

#------------------------------------------------
### 返り値あり関数
def say_something_with_return():
    s = 'hello'
    return s


result = say_something_with_return()
print(result)  # hello


#------------------------------------------------
### 引数あり関数
def what_is_this(color):
    if color == 'red':
        return 'tomato'
    elif color == 'green':
        return 'green pepper'
    else:
        return "I don't know"


result = what_is_this('red')
print(result)  # tomato
result = what_is_this('green')
print(result)  # green pepper

引数や戻り値の型

関数の引数や戻り値は型を明記することができる

ただし、変数の型宣言と同様で、型を強制する力はなく、利用者の使い方次第で渡される型は変わってしまうので注意すること

書き方について以下に記載しておく


def add_num(val1: int, val2: int) -> int:
    return val1 + val2


# 正しい引数を設定した例
a: int = 10
b: int = 20
r = add_num(a, b)
print(r, type(r))  # 30 <class 'int'>

# 誤った使い方で型が変わってしまう例
str_a: str = 'hello,'
str_b: str = 'world.'
r = add_num(str_a, str_b)
print(r, type(r))  # hello,world. <class 'str'>

位置引数とキーワード引数、デフォルト引数

関数の引数には複数の設定方法がある

それぞれの設定方法について以下に記載する


# --------------------------------------------
### 位置引数とキーワード引数
# メニューを出力
def menu(entree, drink, dessert):
    print('entree = ', entree)
    print('drink = ', drink)
    print('dessert = ', dessert)


# 位置引数の例
#   引数を入れる順序が大事なので、以下のように間違った順序にするとおかしな結果になる
menu('beef', 'ice', 'beer')
"""
結果
entree =  beef
drink =  ice
dessert =  beer
"""

# キーワード引数の例
#   キーワードで指定するので引数をいれる順序は関係がない
menu(entree='beef', dessert='ice', drink='beer')
"""
結果
entree =  beef
drink =  beer
dessert =  ice
"""


# --------------------------------------------
### デフォルト引数
# 円周を計算
def calculate_circumference(diameter, pi=3.14):
    return diameter * pi


# 円周率はデフォルト引数の 3.14 で円周を計算
print(calculate_circumference(5))  # 15.700000000000001
# 円周率を 3 で円周を計算
print(calculate_circumference(5, 3))  # 15

デフォルト引数の注意点

デフォルト引数に参照型の変数を設定する際には、以下のことに注意しなければならない


#-----------------------------------------------
### 悪い例
# リストにデータを追加して返す関数
def test_func_ng(x, l=[]):
    l.append(x)
    return l


# リストとして [100] を作りたい処理
r = test_func_ng(100)
print(r)  # [100]

# 別のリストとして [200] を作りたい処理
# ここでリストの中身が前の状態を引き継いでいることに注意
r = test_func_ng(200)
print(r)  # [100, 200]

"""
関数の宣言部分はプログラムを読み込んだ際に1度しか行われない
このタイミングで デフォルト引数 l=[] のアドレスは決まってしまう
2回目以降、同じアドレス先のリストに対して値を追加しようとするため問題が発生する
"""


#-----------------------------------------------
### 良い例
# リストにデータを追加して返す関数
def test_func_ok(x, l=None):
    if l is None:
        l = []
    l.append(x)
    return l


# リストとして [100] を作りたい処理
r = test_func_ok(100)
print(r)  # [100]

# 別のリストとして [200] を作りたい処理
r = test_func_ok(200)
print(r)  # [200]

"""
関数の宣言部分では l=None として、関数内の処理で None の時だけ
新たにリストを生成するように変更している
これにより、別のアドレス先のリストとしてそれぞれ取り扱うことになるため解決できる
"""