Pythonの関数

pythonの関数について勉強したことをまとめていきます。

#関数
関数とは、処理をまとめたものである。
同様の処理を抜き出して共通化させ効率よくコーディングするため、処理を理解しやすくするために利用します。
ちなみにpythonでは、関数名は「_」区切りで宣言するのが慣習のようです。

##定義方法
pythonでの定義方法は、「def 関数名():」というように定義する。関数内の処理は、インデントをずらして記述します。
また、引数を設定したい場合は、()のなかに記述します。

```py:python
# 引数なし
def test_function_1():
    pass

# 引数あり
def test_function_2(arg1, arg2):
    pass
```

javaではこんな感じです。

```java:java
// 引数なし
void testFunction1() {
}

// 引数あり
void testFunction2(String arg1, String arg2) {
}
```

##呼び出し方
pythonでもjava呼び出し方は同じです。関数名()で実行できます。

```py:python
def test_function_1():
    print("関数が実行されました。")

def test_function_2(arg1):
    print("arg1:" + arg1)

#関数を実行
test_function_1() # ⇒ 関数が実行されました。
test_function_2("引数を渡してみた。") # ⇒ arg1:引数を渡してみた。
print(test_function_1()) # ⇒ 関数が実行されました。None
```

```java:java
// 引数なし
void testFunction1() {
    System.out.println("関数が実行されました。");
}

void testFunction2(String arg1) {
    System.out.println("arg1:" + arg1);
}

// 関数を実行
testFunction1(); // ⇒ 関数が実行されました。
testFunction2("引数を渡してみた。"); // ⇒ arg1:引数を渡してみた。
```

戻り値を定義しない場合、関数を実行しても返却されるのは、Noneです。
戻り値を定義したい場合、関数の最後に「return 戻り値」と記述します。

```py:python
def test_function_3():
    return "戻り値を返してみる"

#関数を実行
print(test_function_1()) # ⇒ 戻り値を返してみる
```

javaでも同じなので省略します。


##デフォルト値
pythonの引数には、デフォルト値を設定することができます。設定することによって、関数はデフォルト値を設定した引数を指定しなくても実行することができます。
その場合に、デフォルト値が有効になります。

```py:python
def test_function_3(arg1, arg2 = "引数なし"):
    print("arg1:" + arg1 + " arg2:" + arg2)

#関数を実行
test_function_3("引数1") # ⇒ arg1:引数1 arg2:引数なし
test_function_3("引数1", "引数2") # ⇒ arg1:引数1 arg2:引数2
```

javaにはデフォルト値のような機能はありません。

#可変長引数
pythonで可変長引数を受け取りたい場合は、引数名の前に「*」を付けて関数を定義します。
受け取った結果は、タプルとして関数内で使用できます。慣習では、可変長引数の名前を「*args」としています。ただ、あくまでも慣習なのでargsという名称でなくとも動作します。

```py:python
def test_function_4(*kahen):
    print(kahen)

test_function_4("可変1", "可変2", "可変3") # ⇒ ('可変1', '可変2', '可変3')
```

また、通常の引数と併用も可能です。

```py:python
def test_function_5(arg1, arg2, *kahen):
    print("arg1:" + arg1 + " arg2:" + arg2 + " kahen:" + str(kahen))

test_function_5("不可変1", "不可変2", "可変3", "可変4") # ⇒ arg1:不可変1 arg2:不可変2 kahen:('可変3', '可変4')
```

Javaでは、String...　のように型の後ろに「...」と記述します。

```java:java
// 引数なし
void testFunction4(String... kahen) {
    System.out.println(Arrays.toString(kahen));
}

void testFunction5(String arg1, String arg2, String... kahen) {
    System.out.println("arg1:" + arg1 + " arg2:" + arg2 + " kahen:" + Arrays.toString(kahen));
}

// 関数を実行
testFunction4("可変1", "可変2", "可変3"); // ⇒ [可変1, 可変2, 可変3]
testFunction5("不可変1", "不可変2", "可変3", "可変4"); // ⇒ arg1:不可変1 arg2:不可変2 kahen:[可変3, 可変4]

```


##デコレータ
デコレータとは、Javaには存在しないpython独自の機能です。
関数を引数にとり、関数を戻り値に設定する関数のことです。
言葉だけではわかりにくいので、書いてみます。

```py:Python
def deco(argFun):
    def retFun(arg):
        print("--Start--引数:" + arg)
        argFun(arg)
        print("--End--")
    return retFun

def test_function_6(arg):
    print("Decolated 引数:" + arg)

deco(test_function_6)("TEST")

# --Start--引数:TEST
# Decolated 引数:TEST
# --End--
```

デコレータ関数「deco」を定義しています。
この関数は、関数「retFun」を返却します。
「retFun」は、「deco」が受け取った関数の実行前後に、ログを出力する関数です。
このように、関数「test_function_6」を実行する前後に処理を追加（デコレート）する関数がデコレータです。
こういった方法以外にも「@」修飾子を利用してデコレートできます。

```py:Python
def deco(argFun):
    def retFun(arg):
        print("--Start--引数:" + arg)
        argFun(arg)
        print("--End--")
    return retFun

@deco
def test_function_7(arg):
    print("Decolated@ 引数:" + arg)

test_function_7("test")

# --Start--引数:test
# Decolated@ 引数:test
# --End--
```

以上で関数の説明を終わります。
デコレータの考え方がJavaをやってきた自分にとっては非常に新しく勉強になります。
うまい使用方法がなかなか思い浮かびませんが、使用の仕方次第では非常に分かりにくいコードとなる可能性もありそうなので使用するときには熟考して使用したいと思います。