Python基礎講座(12 関数)

## 関数とは
IT用語辞典によれば、『関数』は
”引数と呼ばれるデータを受け取り、定められた通りの処理を実行して結果を返す一連の命令群”とあります。
プログラム自体がデータを基に処理を行い結果を返すものなので、プログラムは関数の集合体と言えます。
関数を使用せずに、同じ処理を行うプログラムを使用する場所でその都度書いてしまうと、プログラムが冗長になってしまいます。
また修正が必要な場合全ての箇所を修正しなければなりません。
関数化すればプログラムのコードの量を短くすることが出来、修正も関数1箇所を修正すれば良いため手間がかかりません。
後述の「モジュール」を作る際にも必須です。

## 関数の定義
簡単な関数を作成します。
引数として与えた年がうるう年かどうかを判定する関数を使用したプログラムです。
9行目のyearに好きな数値を格納して(現在は2015を格納しています)うるう年を判定する関数
leap_year()が正しく動作することを確認してみましょう。

```py3:leap_year.py
def leap_year(year):
    if year % 400 == 0 or (year % 100 != 0 and year % 4 == 0) :
        leap = True
    else:
        leap = False

    return leap

year = 2015
print("{0} = {1}".format(year,leap_year(year)))
```
関数は以下の形で定義します。

**def** *関数名* **(** *引数* **):**
　　　*処理*
　　　**return** *戻り値*

return文を書かないことで、戻り値の無い関数を定義することも出来ます。

```py3:leap_year2.py
def leap_year(year):
    if year % 400 == 0 or (year % 100 != 0 and year % 4 == 0) :
        print("{0} is leap year".format(year))
    else:
        print("{0} is not leap year".format(year))


year = 2015
leap_year(year)
```

## 引数
通常関数の引数を省略すると、例外が発生します。

```py3:argment_ERRROR.py
def plus_4(arg1,arg2,arg3,arg4):
    return arg1+arg2+arg3+arg4

print("no arg:{0}".format(plus_4()))
```

**TypeError: plus_4() takes exactly 4 arguments (0 given)**

しかし、関数を定義した際に、*引数* **=** *デフォルト値* と記述することで、引数が省略された場合の
デフォルトの値を設定することが出来ます。

```py3:argment_ERRROR.py
def plus_4(arg1=2000,arg2=0,arg3=10,arg4=5):
    return arg1+arg2+arg3+arg4

print("no arg:{0}".format(plus_4()))
```
以下の結果が出力されます。便利ですね。
**no arg:2015**

## 可変長引数
事前に引数の数を決めない関数を作成することが出来ます。

```py3:argments.py
def spam(*args):
	print("{0}".format(args))

spam("arg1",2,3.4)
```

出力結果は
**('arg1', 2, 3.4)**
となります。引数に**\*変数名** と定義することでタプルとして引数に値を渡すことが出来ます。

```py3:argments2.py
def spam(**args):
	print("{0}".format(args))

spam(taro=165,jiro=180,saburo=170)
```

もう1つの可変長引数の定義方法は、引数に**\*\*変数名** と定義することで
ディクショナリとして引数に値を渡すことが出来ます。

## global変数
グローバル(global)変数は、どこからでも参照できる変数です。
関数の外側で宣言することで、関数内でも、関数外でも使用することが出来ます。
逆に言えば、関数の内側で宣言した変数であるローカル(local)変数は関数外では使用できません。

```py3:global_explain.py
var1 = "global"
def hoge(str):
    var2 = "local"
    return var1 + str + var2

print("{0}".format(hoge("-")))
print("{0}".format(var2))
#print("{0}".format(var1))
```
上記のプログラムは実行時例外が発生します。以下のように出力されるはずです。

**global-local
Traceback (most recent call last):
    print("{0}".format(var2))
NameError: name 'var2' is not defined**

変数var2は関数hoge内で宣言された変数のため、外側からは使用することが出来ません。
関数の外側で宣言された変数var1は関数内外で使用することが出来ます。プログラムの
「print("{0}".format(var2))」をコメントアウトし、
代わりに「print("{0}".format(var1))」のコメントを外して再度プログラムを実行してください。
今度は例外が発生しません。

次にglobal変数を関数内で変更する方法を紹介します。

```py3:change_global_NG.py
var1 = "global"

def spam():

	var1 = "change global"
	var2 = "local"
	print(var1,var2)

spam()
print("var1 : {0}".format(var1))
```

**ange global local
var1 : change global**

と表示されることを期待しますが、実際には

**ange global local
var1 : global**

と表示されます。なぜ関数内部でグローバル変数を変更できなかったのでしょうか？
関数内でグローバル変数と同じ名前の変数に値を格納しても、同名のローカル変数として解釈されてしまいます。
関数内でグローバル変数を変更したい場合は、以下のように変数がグローバルだと明記してから変更します。

```py3:change_global.py
def spam():
    global var1
    var1 = "change global"
    var2 = "local"
    print("{0}".format(var1+" "+var2))

spam()
print("var1 : {0}".format(var1))
```

**change global local
var1 : change global**

期待した結果が出力されました。

次: [Python基礎講座(13 クラス)](http://qiita.com/Usek/items/a206b8e49c02f756d636)