関数とは「使い回したい処理に名前をつけたもの」です。
プログラムを組んでいると、同じような処理を何回もすることがあります。そういったときに関数は便利です。
ここでは「関数ってなに?」「関数はどうやって使うの?」「自分で関数を作りたい」といった方へ、関数について解説します。
YouTubeも公開していますので、動画や音声で聞きたい方はぜひご覧ください。
関数の基本的な使い方
それでは関数の使い方を見ていきましょう。
関数は関数名に()をつけて呼び出します。()内には引数を入れます。引数とは「関数内の処理で使うデータ」のことです。
では実際に関数を使ってみましょう。ここではmax()という関数を使います。
max_num = max(38, 10, 64, 37, 9)
print(max_num)
[出力結果]
64
max()は引数で渡した数値のうち、一番大きい数値を見つける関数です。
max()の結果がmax_numに代入され、出力されています。この関数の結果のことを「戻り値」または「返り値」と呼びます。
数値計算で使う関数は、他にも次のようなものがあります。
関数 | 説明 |
---|---|
min(数値1, 数値2, 数値3, …) | 最小値を返します。 |
pow(x, y) | xのy乗を返します。 |
round(数値, 桁数) | 数値を指定した桁数に丸めた結果を返します。 |
ちなみにprint()も関数です。
モジュールの読み込み
次にモジュールを読み込んでみましょう。
モジュールとは、プログラムを作るために使用できる「部品」をまとめたものです。
Pythonでは先ほどのmax()のように、標準で用意されている関数の他に、モジュールを読み込むことで使えるようになる関数があります(標準で用意されている関数は「組み込み関数」と呼びます)。
辞書やwhileの解説で使用したrandomはモジュールです。randomは「ランダムな数値を生成する機能を持った」モジュールです。他にも数学関連のmathモジュールや、日付や時間を操作するdatetimeモジュールなどがあります。このようにモジュールは各目的ごとに分割されています。
ではモジュールを読み込んでみましょう。読み込みはimport文を使います。
import math
ceil_num = math.ceil(28.45) #切り上げ
floor_num = math.floor(28.45) #切り捨て
print(ceil_num)
print(floor_num)
[出力結果]
29
28
mathモジュールのceil()とfloor()関数を使いました。どちらも数値を引数にとり、ceil()は切り上げ、floor()は切り捨てをする関数です。読み込んだモジュールの関数を使うには、モジュール名を関数名で指定します。
[構文]
モジュール名.関数名()
自分で関数を作る
さて、ここまではPythonが用意してくれていた関数を使って、関数の使い方を見てきました。ここからは、自分で関数を作る方法を学んでいきましょう。
次のプログラムを見てください。
def compare_length(str1, str2):
length1 = len(str1)
length2 = len(str2)
if (length1 > length2):
result = str1
else:
result = str2
return result
str1 = "なまむぎなまごめなまたまご";
str2 = "あおまきがみあかまきがみきまきがみ";
print(compare_length(str1, str2))
[出力結果]
あおまきがみあかまきがみきまきがみ
これは「2つの文字列のうち、長い文字列の方を出力する」プログラムです。
ここではcompare_length()という関数を新たに作成しています。ユーザー定義関数は、先頭にdefをつけることで作成できます。引数がある場合は関数名の後に続く括弧内に定義します。今回は2つの文字列の長さを比較するので、str1、str2を引数にとります。
関数内では2つの文字列の長さをlen()で取得し、ifを使って比較しています。最後に比較して長かった方の文字列を、return文を使って返却して、returnした結果が「戻り値」となります。
以上がユーザー定義関数の作り方になりますが、関数を作るときもインデントが必要です。インデントがないとエラーになるので注意しましょう。
[構文]
def 関数名(引数1, 引数2, 引数3, ...):
#インデント開始
命令1
命令2
命令3
return 戻り値
#インデント終了
戻り値のない関数
戻り値のない関数を定義することもできます。次のコードを見てください。
def compare_length(str1, str2):
length1 = len(str1)
length2 = len(str2)
if (length1 > length2):
print(str1)
else:
print(str2)
str1 = "なまむぎなまごめなまたまご";
str2 = "あおまきがみあかまきがみきまきがみ";
compare_length(str1, str2)
先ほどの関数の、戻り値がないパターンです。戻り値が必要ない場合は、このような作り方も可能です。
関数で使う変数のスコープ
ローカル変数
変数はどこで作られたかによって、使える範囲が変わってきます。
変数が使える範囲のことを、変数の「スコープ」と呼びます。
まずは例を見てみましょう。
def calc():
a = 1
b = 2
print(1 + 2)
calc()
[出力結果]
3
非常にシンプルな関数のcalc()を定義し、呼び出しています。
これについては何も問題ありません。
では次に、関数内の変数aを、関数の外で読んでみましょう。
def calc():
a = 1
b = 2
print(1 + 2)
print(a)
[出力結果]
NameError: name 'a' is not defined
結果はNameErrorでした。
NameErrorは「初期化していない変数を参照したときに起こるエラー」です。
つまり変数aを出力しようとした箇所では、変数aは初期化されていない状態です。その理由は関数内で初期化した変数は、関数内でしか使えないからです。こういった「使える場所が制限されている変数」のことを、ローカル変数と呼びます。
では、関数の外で同じように変数aを初期化するとどうなるのでしょうか?
実際にやってみましょう。
def calc():
a = 1
b = 2
print(1 + 2)
a = 10
print(a)
[出力結果]
10
今度はエラーにならず、10が出力されました。
関数の中の変数と外の変数は、変数名が一緒でも異なる変数として扱われます。
グローバル変数
次にグローバル変数について見ていきましょう。
グローバル変数はローカル変数の反対で「使える場所が制限されない変数」を指します。
次の例を見てください。
a = 10 #グローバル変数
def calc():
b = a * 10
print(b)
calc()
[出力結果]
100
変数aは関数の外で作成されているグローバル変数です。
グローバル変数は関数の内外で使うことができます。calc()では変数bに a * 10 の計算結果を代入し、最後に出力しています。結果が100になっているので、変数aが関数内でも使えているのがわかります。
無名関数
最後に無名関数を見ていきましょう。
無名関数はラムダ式を使って書きます。例を見てみましょう。
func = lambda a, b : a + b
sum = func(3, 5)
print(sum)
[出力結果]
8
先ほどまでの関数と、書き方が全く違うことが分かるかと思います。
1行目でラムダ式を使っています。
[構文]
lambda 引数1, 引数2, 引数3, … : 処理する内容
ここで最も重要なのは「関数をfuncという変数に代入」していることです。
今までは、変数はデータを入れる箱としてのみ使っていましたが、ここでは変数に無名関数を入れています。こうしてできたfuncを「関数オブジェクト」と呼びます。
関数オブジェクトには引数を渡すことができます。上記のプログラムでは2つの数値を引数で渡し、最後に結果を出力しています。これが無名関数の使い方です。
また、ラムダ式は変数に代入せず、そのまま実行することもできます。代入しない場合、先ほどのプログラムは1行で記述できます。
sum = (lambda a, b : a + b)(3, 5)
print(sum) #結果は同じ
リストから条件に合う要素を抜き出す - filter()
無名関数の代表的な使い方の一つにfilter()という関数があります。
filter()は「リストや辞書などのイテラブルから、条件に合う要素を抽出する」関数です。実際に使ってみましょう。
source_nums = [-3, -2 ,-1, 0, 1, 2, 3]
result_nums = list(filter(lambda x : x >= 0, source_nums))
print(result_nums)
[出力結果]
[0, 1, 2, 3]
filter()の第一引数が無名関数、第二引数がリストです。source_numsの数値を一つずつ取り出し、xに代入します。x >= 0がTrueになる数値のみ抽出し、新しくリスト作りresult_numsに代入しています。