見出し画像

Python無学エンジニアの資格挑戦記 #5 関数の基礎

Python学習の第5回目。
前回は変数や型変換、代入文、ターミナルへの入出力について学習した。

今回は、一連の処理をまとめる「関数」の基礎について学んでいく。
関数を覚えることで、処理の重複をなくしたり、同じ処理を再利用しやすくなったりするんだ。

それじゃ、いってみよう。

関数の利用

多くのプログラミング言語では、一連の処理をまとめる方法がある。
Pythonではそれを「関数」と呼び、よく使われる処理の一部は、あらかじめ関数として言語内に組み込まれている。

これまでに出てきたprint関数やinput関数、int関数、float関数、str関数も、予め言語内に組み込まれている関数だね。

これらの関数は、以下の形式で利用する。

$${関数名(引数1, 引数2, 引数3, …)}$$

関数に渡す値を「引数」と呼ぶよ。
例えば、絶対値を返す「abs関数」は、1つだけ引数を受け取るんだ。

新たにfunc_use.pyファイルを作成し、以下のプログラムを実行してみよう。

val = abs(-200)
print(val)
関数を利用したプログラム

「200」が表示された。
abs関数は引数「-200」を受け取り、絶対値である「200」を結果として返している。
その値をval変数に代入し、print関数でターミナルに出力しているんだ。

上記の200のように関数が返す結果のことを、「戻り値」や「返り値」と呼ぶ。
ちなみに俺は、返り値というと「返り血」に聞き間違えられて怖いから、戻り値と呼ぶようにしているよ。

別の関数も見てみよう。
べき乗を計算する「pow関数」は、2つ引数を受け取る。
func_use.pyに以下のプログラムを追加して実行しよう。

val = pow(2, 3)
print(val)
2つの引数を持つpow関数

「8」が表示された。
pow関数は第1引数に2、第2引数に3を受け取り、2³である8を戻り値として返しているんだ。

関数は演算子と同じように、計算式の一部として扱うことができる。
だから、以下のように関数の引数を書く場所に計算式を組み込んだり、計算式の一部に関数を含めることもできるんだ。

$${fuga = 関数(hoge1 * hoge2) + hoge3}$$

例として、pow関数を使って直径から円の面積を計算する処理がある。
func_use.pyに以下のプログラムを追加して実行しよう。

diameter = 10
pi = 3.14
area = pow(diameter / 2, 2) * pi
print(area)
関数が計算式の一部に組み込まれている

「78.5」が表示された。

円の面積は《半径の2乗×円周率》で求められる。
この処理の場合、直径10を2で割り、その値をpow関数に渡す。
関数の戻り値に円周率3.14をかけて、area変数に代入しているんだ。

このように、関数は通常の演算子と同様にプログラム内に組み込むことができるよ。

関数の定義

では、自分で関数を作るにはどうしたらいいんだろう。
円錐の体積を求める関数を例として考えてみよう。

Pythonでは、関数を定義するには以下のようにする。

$${def 関数名(引数1, 引数2, 引数3, …):}$$

関数の戻り値は以下のようにして定義する。

$${return 式}$$

なお、関数内の処理はインデントを入れて記述する。
Pythonでは構文の入れ子を表すために、インデントを使うんだ。
これは、Python文法の大きな特徴のひとつと言えるね。

CやJava、PHPでも、可読性のためにインデントは入れるけど必須ではない。
これらの言語では、構文の入れ子は中括弧{}で表す。
それがPythonではインデントとなるんだ。

新たにfunc_def.pyファイルを作成し、以下のプログラムを実行してみよう。

def cone_volume(diameter, height):
    return ((pow((diameter / 2), 2) * 3.14) * height) / 3

print(cone_volume(10, 7))
VSCodeでは関数内に自動でインデントを入れてくれる

「183.1666…」が表示された。

cone_volumeという円錐の体積を求める関数を新たに定義し、その関数をprint関数の中から10と7という引数を与えて呼び出しているよ。
自分で作った関数でも、言語内に定義されている関数と呼び出し方は同じだ。

Pythonではタブと半角スペースのどちらでもインデントに使用できる。
しかし、タブと半角スペースが混在するとエラーが発生したり、タブのみを使用したプログラムを閲覧すると、エディタによりタブ幅が異なり、見た目が変わってしまうという問題が発生する。

なお、Pythonの入力規則であるPEP8では、インデントについてこう記載されている。

タブか、スペースか?
スペースが好ましいインデントの方法です。
タブを使うのは、既にタブでインデントされているコードと一貫性を保つためだけです。
Python では、インデントにタブとスペースを混ぜることを禁止しています。

pep8-ja 1.0 ドキュメントより一部抜粋

ここでは、半角スペース4つを基本として使うことにするね。

ローカル変数と引数

自作した関数の中でも、変数を使ったり処理を記載することができる。
その際、関数の処理は定義した関数の内部処理であることを示すために、インデントを入れる必要があるんだ。

func_def.pyを以下のように書き換えて実行しよう。

def cone_volume(diameter, height):
    pi = 3.14
    area = pow((diameter / 2), 2) * pi
    return (area * height) / 3

print(cone_volume(10, 7))
関数の中に処理を書く

結果はさっきと同じ、「183.1666…」が表示された。

関数の中で定義された変数は「ローカル変数」と呼ばれ、その関数の中でのみ使用できる。
このプログラムの場合、「pi」「area」はローカル変数となる。

関数の外でローカル変数にアクセスすることはできない。

func_def.pyを以下のように書き換えて実行しよう。

def cone_volume(diameter, height):
    pi = 3.14
    area = pow((diameter / 2), 2) * pi
    return (area * height) / 3

print(cone_volume(10, 7))
print(area)  # この行を追加
エラーとなってしまう

NameErrorが表示され、7行目の変数「area」が定義されていないと表示されてしまった。
これはareaがローカル変数で、関数外ではアクセスできないためだ。

では、関数の引数はどうだろうか。
func_def.pyを以下のように書き換えて実行しよう。

def cone_volume(diameter, height):
    pi = 3.14
    area = pow((diameter / 2), 2) * pi
    return (area * height) / 3

print(cone_volume(10, 7))
print(diameter)  # この行を変更
再びエラーとなってしまう

先ほどと同じくNameErrorが表示され、7行目の変数「diameter」が定義されていないと表示された。
関数の引数も同様に、関数外ではアクセスできない変数となるんだ。

グローバル変数とスコープ

Pythonでは、関数の外で定義された変数は「グローバル変数」と呼ばれ、関数内からもアクセスできる変数として扱われる。

新たにglobal_variable.pyファイルを作成し、以下のプログラムを実行してみよう。

g_variable = 10

def print_variable():
    print(g_variable)

print_variable()
関数の中から変数にアクセスする

ターミナルには「10」が表示された。
関数の外で代入された「g_variable」はグローバル変数となり、関数の中でもアクセスが可能になるんだ。

つまり、以下のようになる。

$$
\begin{matrix*}[c]
\textsf{変数のアクセス範囲}
\end{matrix*}
\\
\begin{array}{|l|l|l|l|}
\hline
\text{\small 変数定義位置} & \text{\small 変数の種類} & \text{\small 関数の外} & \text{\small 関数の中} \\ \hline
\text{\small 関数の外} & \text{\small グローバル変数} & \text{\small アクセス可能} & \text{\small アクセス可能} \\ \hline
\text{\small 関数の中} & \text{\small ローカル変数} & \text{\small アクセス不可} & \text{\small アクセス可能(※)} \\ \hline
\end{array}
$$

※ただし、変数定義した関数の中のみ

また、関数の中でグローバル変数と同じ名前で変数定義をすると、その変数はグローバル変数とは別のローカル変数として扱われるんだ。

global_variable.pyを以下のように書き換えて実行しよう。

g_variable = 10
variable = 20

def print_variable():
    variable = 30
    print(g_variable)  # グローバル変数
    print(variable)    # ローカル変数

print_variable()
print(variable)  # グローバル変数
ローカル変数とグローバル変数の名前を同じにする

順に「10」「30」「20」と表示された。

関数「print_variable」の中では、2つの変数をprintしている。
その中で変数「variable」は2行目と5行目で変数定義しており、2行目はグローバル変数、5行目は関数内のためローカル変数として扱われている。

7行目では、関数内で定義されたローカル変数「variable」の値である「30」が表示される。
その一方で、グローバル変数は別のものとして扱われるため、10行目ではグローバル変数「variable」の値である「20」が表示されるんだ。

Pythonプログラムでは、関数以外の部分を「モジュールスコープ」と呼び、関数内の部分を「ローカルスコープ」と呼ぶ。
モジュールスコープで代入された変数はグローバル変数となり、ローカルスコープで代入された変数はローカル変数となるんだ。

まとめ

今回は関数の仕組みと作り方について学んでいった。

基本的な部分は他のプログラミング言語と似ているけど、ひとまとまりの処理をインデントで表すというPython独特の文法が出てきたね。
この点は、慣れるまではプログラムが少し読み解きにくいかもしれない。

次回は比較演算と条件分岐について学んでいくよ。
無理せず頑張っていこう。

最後まで読んでくださりありがとうございます。
記事が少しでもあなたの心に残ったら、【スキ】で知らせてくれると嬉しいです。
それでは、また!

#Masaharuの学び記録 #ITメモ

参考資料

PEP8 日本語版
https://pep8-ja.readthedocs.io/ja/latest/

東京大学 - Pythonプログラミング入門
https://utokyo-ipp.github.io/

Python Japan - ゼロからのPython入門講座
https://www.python.jp/train/index.html

いいなと思ったら応援しよう!

この記事が参加している募集