この章のキーワード
- 関数
- def
- 関数の呼び出し
- 値を返す関数
- 引数
- return
- ローカル変数
- グローバル変数
- global宣言
- スコープ
- Pythonのマニュアル
この章のキーワード
プログラムが長くなってくると、似たようなコードが何度も出てくることがあります。何度も同じことを書くのは無駄が多いので、同じコードを一回書けば他でも使えるようにする仕組みが 関数(かんすう) です。
最初はシンプルな、ある値を表示するだけの関数を作ってみましょう
def version(): v = "0.01" print(v)
version()
このプログラムを実行すると、“0.01”が表示されます。
上記のコードで、defから始まるブロック(1行目~3行目)が関数の定義の部分です。5行目からはメインルーチンの部分で、ここでは関数 version
を呼び出しています。
def
で関数を定義します。 def(デフ) は、definition(デフィニション)の略で、英語で「定義」と言う意味です。今回は、 version
という名前の関数を作りました。関数を作るときはdefの後に関数名を書き、最後に ()
をつけます。また、行の最後には :
をつけることも忘れずに。関数の内容はその下に字下げ(インデント)を行って書きます。
この関数の中身は簡単で、 v
という変数に文字列”0.01”を入れて、print文で表示させています。
def version(): v = "0.01" print(v)
作った関数を使うには、関数名の後に ()
つきで呼び出します。一度作った関数は何度でも使うことができます。
version()
関数 version
は、呼び出したら画面に数字を表示するだけでした。今度は、データを処理する関数を作ってみます。2つの数字の平均を計算してくれる関数にしましょう。
def heikin(a,b): h = (a+b)/2 return h
print(heikin(5,11))
このプログラムを実行すると、8.0が表示されます。
関数を呼び指す際に、計算に必要な値を関数に渡します。この関数に渡す値のことを 引数(ひきすう) と呼びます。引数は ()
の中に入れます。
この例では、5と11という引数を関数に渡しています。
print(heikin(5,11))
関数 heikin
は、2つの数を受け取るとその平均を計算します。このコードでは、 a
と b
がその2つの数です。aは5を、bは11を受け取ります。引数は、呼び出す際の順番(5が1番目、11が2番目)と関数定義での順番( a
が1番目、 b
が2番目)が対応しています。
関数の定義のブロックの最初の行を見てみましょう。
def heikin(a,b):
ここまで紹介してきた関数の引数の渡し方・受け取り方は「位置引数」と呼ばれる方法です。この方法とは別に、以下のような「キーワード引数」と呼ばれる方法もあります。
関数名(引数名=値)
キーワード引数では、関数呼び出し側で「引数名=値」というキーワードを使って値を受け渡します。この時の「引数名」は、関数定義の時に使った引数名(仮引数)です。この場合、並べる順番は関係ありません。上記の例で呼び出し側を下記のように書いても同じことになります。
print(heikin(b=11,a=5))
関数を呼び出した場所で関数の計算結果を使うために、関数は計算結果を「戻す」ことが必要になります。関数が値を戻すには return
(リターン) を使います。なお、このような値を 戻り値(もどりち) や 返り値(かえりち) と呼びます。下記では、hが戻り値です。
return h
引数を5と11として関数 heikin
を呼び出し、関数から戻ってきた結果(戻り値)をprint文で表示します。
print(heikin(5,11))
3つの数字を引数として与えられたら、そのうちの一番小さいものを返す関数を作ってみましょう。
関数の中で変数を使うときには注意が必要です。たとえば下のコードで、関数 setb
の中で変数 b
を作って20を代入しています。最後の行のprint文で変数 b
を表示するとどうなるでしょうか?
def setb(): b = 20
setb()print(b)
setb.pyを実行すると「name ‘b’ is not defined」 というエラーが出ます。「bが定義されていません」という意味です。
関数 setb
の中で変数 b
を定義して20を代入しています。関数の中で変数を作ると、 ローカル変数 になり、関数の外では使うことができない変数になります。ローカルというのは、「狭い場所」という意味です。
def setb(): b = 20 #bはローカル変数とみなされる
5行目は関数の外のコードです。外から変数bを見ることはできません。そのために「bは定義されていません」というエラーが出るのです。
print(b)
今度は、外で定義された変数を関数の中で使ってみましょう。
a = 10
def printa(): print(a)
printa()
このコードを実行すると、10が出力されます。
1行目で、変数 a
を定義して10を代入しています。この変数は関数の外側にあるので、 グローバル変数 といいます。グローバル変数はプログラムのどこからでも使う(見る)ことができます。グローバルとは「広い場所」という意味です。
a = 10
4行目では、関数 printa
の中でグローバル変数 a
を表示しています。
def printa(): print(a) #グローバル変数はどこででも見ることができる
関数の中でもグローバル変数を読み取ることができるのはわかりましたが、次のような例はどうでしょうか?
プログラム1
a = 10
def seta(): a = 20
seta()print(a)
このコードを実行すると、なんと10が表示されます。どうしてだろう??
4行目では関数 seta
の中でグローバル変数 a
に20を代入しているように見えます。しかし、通常は 関数の中ではグローバル変数を変更できない ので、実際には a
という 同じ名前だけど別物 のローカル変数が新しく作られて20が代入されているのです。
def seta(): a = 20 #ここのaは、外で10を代入したaとは別物とみなされる
このため、グローバル変数 a
は変更されておらず、6行目では10が表示されます。
print(a)
関数内でグローバル変数を使いたい場合はこのようにします。 プログラム1 と見比べてみてください。
プログラム2
a = 10
def seta(): global a a = 20
seta()print(a)
関数内でグローバル変数を操作したいときは global宣言 (グローバルせんげん)を行います。4行目の global a
でグローバル変数 a
を関数 seta
内で使用する、と宣言すると、 seta
の中での変数 a
はグローバル変数の a
とみなされ、変更できます。
def seta(): global a a = 20
「時蕎麦(ときそば)」という落語を知っていますか?男の客は蕎麦代として1文銭を16枚払わなければいけないところ、数えている途中で蕎麦屋に時刻を尋ねることで数(カウント)をごまかし、結局15枚しか払わなかった、という話です。カウントの途中でカウンターをいじられると間違った結果になってしまうという例です。時蕎麦をご存知の方は、思い出しながら下記の例を楽しんでみてください。
下記のプログラムをコピーして、自分のPCで実行してみてください。
やってみよう1
まず、このまま実行して、男の客が支払った金額を確かめてみてください。正しく16文支払っているでしょうか。ここでは関数 ima_nandoki()
に global i
があります。つまり、グローバル変数とローカル変数が 区別がない 場合で、関数の中からグルーバル変数 i
を変更できる状況です。関数内で i = ima
とすると、グローバル変数の i
が変更されます。
やってみよう2
次に、 jikoku
を9ではなく4に変更して実行してみましょう。落語のオチ(余計に払ってしまった)のようになりましたか?
やってみよう3
ここから、ローカル変数・グローバル変数の話です。今度は global i
をコメントにするか削除するかして実行し、先ほどとの違いを確かめてみてください。ここではグローバル変数とローカル変数の区別がある場合で、関数内で i = ima
としてもこの i
はローカル変数とみなされ、グローバル変数の i
は変更されません。
def ima_nandoki(ima): global i #この行をコメントアウトするか削除するかして実行し、結果を比べてみてください print() print("男の客:今何時(なんどき)でい!") print("蕎麦屋:へい、",ima, "つでい。") print("男の客:おう。",ima, "つかい。じゃあ、\n\t",end="") i = ima
#---<メインルーチン>---# 下記の変数jikokuは時刻(〇つ時)を示します。9つ時は深夜0時です。# これを4(4つ時は夜の10時)に変えてみてください。何文払ったでしょうか。jikoku = 9saisho = True
print("<時蕎麦> 時刻は",jikoku,"つ時")print("男の客:一文銭で16文払うぜ。\n\t",end="")i = 1while i <= 16: print(i,",",end="") if i == 8 and saisho == True: saisho = False ima_nandoki(jikoku) i += 1print()print("男の客:御馳走様!")
実際のプログラミングの現場では、関数の中でグローバル変数を変更しているつもりが、このグローバル宣言を書き忘れているために、うまく動かないということがしょっちゅうあります。誰でもやります。この場合、エラーが出ないのでなかなか気づけないものなのです。
「関数の中でグローバル変数を変えたい場合は グローバル宣言を忘れずに! 」
#バグを含んだプログラム
def ima_nandoki(): global i #ここを無くして実行して比べてみてください print() print("男の客:今何時(なんどき)でい!") print("蕎麦屋:へい、九(ここの)つでい。") print("男の客:おう。九つかい。じゃあ、") i = 9
print("<時蕎麦>")print("男の客:一文銭で十六文払うよ")i = 1while i <= 16: print(i,",",end="") if i == 8: ima_nandoki() i += 1print()print("男の客:御馳走様!")
Pythonは関数の中身を書かないとエラーになりますので、注意してください。
それでは、なにもしない関数 nanimosinai
を作って呼び出すプログラムを作ってみてください。エラーにしないためには、関数の中身として「なにもしない」という意味のコードを書く必要があります。Google検索やPythonのマニュアルを探索して「なにもしない」ためのコードを調べてみましょう。