Python備忘録3(関数)

# 関数
## def1
```python:def1.py
def print_hello():
    print('Hello')

print_hello()
```

```console:console
Hello
```

## def2
```python:def2.py
def print_hello(name):
    print(f'Hello {name}!')

print_hello('towamz')
```

```console:console
Hello towamz!
```
- 引数を設定できる。


## def3
```python:def3.py
def print_hello(name='there'):
    print(f'Hello {name}!')

print_hello()
print_hello('towamz')
```

```console:console
Hello there!
Hello towamz!
```
- 引数にデフォルト値を設定できる



## def4
```python:def4.py
def print_hello(*names):
    for name in names:
        print(f'Hello {name}!')

print_hello()
print_hello('towamz','jo')
```

```console:console
Hello towamz!
Hello jo!
```

- 引数に*をつけると、タプルで引数を受け取る。引数の数は可変。


## def5
```python:def5.py
def print_cat(**catInfo):
    for k in catInfo:
        print(f'{k}={catInfo.get(k)}')

print_cat(type='cat',fur='white',gender='male')
```

```console:console
type=cat
fur=white
gender=male
```

- 引数に**をつけると、ディクショナリで引数を受け取る。引数の数は可変。


## def6
```python:def6.py
def functionSample(arg1,*arg2,**arg3):
    print(f'{arg1=},{arg2=},{arg3=}')

functionSample(1,2,3,4,5,name='towamz',age=20)
```

```console:console
arg1=1,arg2=(2, 3, 4, 5),arg3={'name': 'towamz', 'age': 20}
```

- 通常の引数。タプル型可変引数。ディクショナリ型可変引数を同時に指定できる。

## inner関数
```python:def-inner.py
# 関数内に関数を書ける(we can put a function inside a function)
def funcOut():
    def funcIn():
        print('innerFunction')
    funcIn()

funcOut()
# インナー関数は直接呼び出せない(Inner functions cannot be called directly)
funcIn()
```

```console:console
innerFunction
Traceback (most recent call last):
  File "def-inner.py", line 10, in <module>
    funcIn()
NameError: name 'funcIn' is not defined
```

# scope
## local scope
```python:localScope.py
def checkScope():
    pet = 'cat'
    print(f'関数内:{pet},{id(pet)}')

pet = 'dog'
checkScope()
print(f'関数外:{pet},{id(pet)}')
```

```console:console
関数内:cat,139817805712752
関数外:dog,139817805713200
```


## global scope
```python:globalScope.py
def checkScope():
    global pet 
    pet = 'cat'
    print(f'関数内:{pet},{id(pet)}')

# pet = 'dog'
checkScope()
print(f'関数外:{pet},{id(pet)}')
```

```console:console
関数内:cat,140466196876656
関数外:cat,140466196876656
```


## nonlocal scope
```python:nonlocalScope.py
def func1():
    Val = 'func1'
    def func2():
        nonlocal Val
        Val = 'func2'
        def func3():
            nonlocal Val
            Val = 'func3'
            print(f'{Val = },{id(Val) = }')

        func3()
        print(f'{Val = },{id(Val) = }')
    func2()
    print(f'{Val = },{id(Val) = }')
func1()

```

```console:console
Val = 'func3',id(Val) = 139659068084016
Val = 'func3',id(Val) = 139659068084016
Val = 'func3',id(Val) = 139659068084016
```

```python:nonlocalScope2.py
# nonlocalを宣言しないと関数ごとに違う変数となる
def func1():
    Val = 'func1'
    def func2():
        Val = 'func2'
        def func3():
            Val = 'func3'
            print(f'{Val = },{id(Val) = }')

        func3()
        print(f'{Val = },{id(Val) = }')
    func2()
    print(f'{Val = },{id(Val) = }')
func1()
```

```console:console
Val = 'func3',id(Val) = 139942491885360
Val = 'func2',id(Val) = 139942491885104
Val = 'func1',id(Val) = 139942491838384
```


# ジェネレーター関数
## ジェネレーター関数1
```python:generator1.py
def generatorFunc():
    n = 100

    for _ in range(10):
        yield n
        n += 1

gen = generatorFunc()

for _ in range(11):
    # yieldで返した値を受け取る
    n = next(gen)
    print(f'{n=}')
```

```console:console
n=100
n=101
n=102
n=103
n=104
n=105
n=106
n=107
n=108
n=109
Traceback (most recent call last):
  File "generator1.py", line 12, in <module>
    n = next(gen)
StopIteration
```
- yieldの引数を返しそこで処理が止まる。nextでyieldの次から処理を再開する。
- 関数の最後に達しyieldが実行できない場合は[StopIteration]例外が発生する。


## ジェネレーター関数2
```python:generator2.py
def generatorFunc():
    n = 0
    while True:
        # send()の値を受け取る
        sendVal = yield n

        # next()を実行したときはyieldは[None]を返す
        if sendVal == None:
            n += 1
        else:
            n = sendVal

gen = generatorFunc()

for _ in range(10):
    n = next(gen)
    print(f'{n=}')

n = gen.send(150)
print(f'send{n=}')

for _ in range(10):
    n = next(gen)
    print(f'{n=}')

# generator関数を終了する
gen.close()

# generator関数を終了した後nextを実行するとStopIteration例外が発生する
n = next(gen)
```

```console:console
n=0
n=1
n=2
n=3
n=4
n=5
n=6
n=7
n=8
n=9
sendn=150
n=151
n=152
n=153
n=154
n=155
n=156
n=157
n=158
n=159
n=160
Traceback (most recent call last):
  File "generator2.py", line 31, in <module>
    n = next(gen)
StopIteration
```



## ジェネレーター関数3
```python:generator3.py
def generatorFunc():
    n = 100

    for _ in range(10):
        yield n
        n += 1

gen = generatorFunc()

print(f'{next(gen)}')

gen.throw(Exception('unexpected Errorです'))
```

```console:console
100
Traceback (most recent call last):
  File "generator3.py", line 12, in <module>
    gen.throw(Exception('unexpected Errorです'))
  File "generator3.py", line 5, in generatorFunc
    yield n
Exception: unexpected Errorです
```



## サブジェネレーター関数
```python:sub-generator.py
def generator3rd():
    for i in range(100,105):
        yield "g3-y" + str(i)
    return "g3-r"

def generator2nd():
    for i in range(10,15):
        yield "g2-y" + str(i)
    g2r = yield from generator3rd()
    print("g2r:",g2r)
    return "g2-r"

def generator():
    yield "g-y"
    gr = yield from generator2nd()
    print("gr:",gr)
    return "g-r"


gen = generator()

for _ in range(20):
    print(next(gen))
```

```console:console
g-y
g2-y10
g2-y11
g2-y12
g2-y13
g2-y14
g3-y100
g3-y101
g3-y102
g3-y103
g3-y104
g2r: g3-r
gr: g2-r
Traceback (most recent call last):
  File "sub-generator.py", line 27, in <module>
    print(next(gen))
StopIteration: g-r
```

# 高階関数
```python:higherOrderFunction.py
def funcSub1(name):
    print(f'Hi! {name}')

def funcSub2(name):
    print(f'Bye! {name}')

def funcRtn(msg):
    print(f'{msg}')

def funcRoot(fn):
    fn('towam')
    return funcRtn


var1 = funcRoot(funcSub1)
var1('こんにちは')

var2 = funcRoot(funcSub2)
var2('さようなら')

```

```console:console
Hi! towam
こんにちは
Bye! towam
さようなら
```
- 高階関数は、関数を引数・戻り値にする関数のこと



# lambda
## 三項演算子
```python:ternaryOperator.py
vals = '0','a'

for i in vals:
    judge = "数字です" if i.isdigit() else "数字ではありません"
    print(judge)
```

```console:console
数字です
数字ではありません
```
- [Trueの時に返す値] if [条件式] else [falseの時に返す値]


## lambda1
```python:lambda1.py
l1 = lambda : print('Hello World')
l1()
```

```console:console
Hello World
```
- lambdaは、関数を１行で定義し関数名を付けない


## lambda2
```python:lambda2.py
l2 = lambda x: print(f'{x}を受け取りました')
l2('towamz')
```

```console:console
towamzを受け取りました
```
- lambdaは、引数を受け取ることができる


## lambda3
```python:lambda3.py
l3 = lambda x,y,z: x if all((x>y,x>z)) else y if y>z else z
print(l3(1,5,10))
print(l3(15,5,10))
print(l3(15,20,10))
```

```console:console
10
15
20
```
- lambdaは、条件分岐できる

# 再帰関数
## fibonacci number
```python:recursive-fibonacci.py
def getfibonacciNumber(n):
    global result

    # listの要素数が不足している場合は要素を追加する。値は計算未実行の-1を代入。
    if len(result) <= n:
        result += [-1] * (n - len(result) + 1)
        print('afterExtentionExec:',result)

    # 計算未実行のときは計算する
    if result[n] == -1:
        print('calculation exec:',n)
        result[n] = getfibonacciNumber(n - 1) + getfibonacciNumber(n - 2)

    return result[n]
 


result = [0,1]

print('--')
i = 10
print(i,len(result),result)
print(getfibonacciNumber(i))
print(i,len(result),result)

print('--')
i = 15
print(i,len(result),result)
print(getfibonacciNumber(i))
print(i,len(result),result)

print('--')
i = 5
print(i,len(result),result)
print(getfibonacciNumber(i))
print(i,len(result),result)
```

```console:console
--
10 2 [0, 1]
afterExtentionExec: [0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
calculation exec: 10
calculation exec: 9
calculation exec: 8
calculation exec: 7
calculation exec: 6
calculation exec: 5
calculation exec: 4
calculation exec: 3
calculation exec: 2
55
10 11 [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
--
15 11 [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
afterExtentionExec: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, -1, -1, -1, -1, -1]
calculation exec: 15
calculation exec: 14
calculation exec: 13
calculation exec: 12
calculation exec: 11
610
15 16 [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]
--
5 16 [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]
5
5 16 [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]
```


# デコレーター関数
```python:decoretor.py
def decoretorFunction(argumentFunction):
    def wrapper(*args, **kwargs):
        print('共通の処理開始')
        argumentFunction(*args, **kwargs)
        print('共通の処理終了')
    return wrapper


@decoretorFunction
def decoretorSubfunc1(*args, **kwargs):
    print('Subfunc1を開始')
    for i in range(args[0],args[1]):
        print(i)
    print('Subfunc1を終了')

@decoretorFunction
def decoretorSubfunc2(*args, **kwargs):
    print('Subfunc2を開始')
    for i in range(args[0],args[1]):
        print(i ** 2)
    print('Subfunc2を終了')


decoretorSubfunc1(10,20)
print('-' * 10)
decoretorSubfunc2(10,20)
```

```console:console
共通の処理開始
Subfunc1を開始
10
11
12
13
14
15
16
17
18
19
Subfunc1を終了
共通の処理終了
----------
共通の処理開始
Subfunc2を開始
100
121
144
169
196
225
256
289
324
361
Subfunc2を終了
共通の処理終了
```


# map関数
## map1
```python:map1.py
decimalNumber = [1,2,4,8,16,32]

decimalNumberShitf = map(lambda x:x * 2, decimalNumber)

for x,y in zip(decimalNumber,decimalNumberShitf): 
    print(x,y)

print(decimalNumberShitf)
```

```console:console
1 2
2 4
4 8
8 16
16 32
32 64
<map object at 0x7f2020957ee0>
```



## map2
```python:map2.py
def isDivisible(x,y):
    if x % y == 0:
        return True
    else:
        return False

results = map(isDivisible, range(10,15), [3,2,3,5,7])
for x in results:
    print(x)
```

```console:console
False
False
True
False
True

# 参考
False　#10/3は割り切れない
False　#11/2は割り切れない
True   #12/3は割り切れる
False  #13/5は割り切れない
True   #14/7は割り切れる
```

# zip関数
## zip1
```python:zip.py
list1 = [i for i in range(0,5)]
list2 = [i for i in range(10,15)]

print(list1,list2)

list3 =[i + j for i,j in zip(list1,list2)]
print(list3)
```

```console:console
[0, 1, 2, 3, 4] [10, 11, 12, 13, 14]
[10, 12, 14, 16, 18]
```





## 
```python:.py

```

```console:console

```