Pythonの理解の乏しい文法を補う記事

# はじめに

Pythonをかけると言っても,所々にわからない文法があるかと思います。

そんなものを一つずつ公式ドキュメントを調べつつ,実験したいと思います。

- argparse
- decorator
- class method v.s. static method
- property , setter
- Union
- yield
    - 追記. 
    - torchのstack
    - ABCclass

次回 : [torch/autograd/grad_mode.pyのgithub](https://github.com/pytorch/pytorch/blob/master/torch/autograd/grad_mode.py)を理解します。

# 1. [argparse](https://docs.python.org/ja/3/library/argparse.html#module-argparse)

プログラムの仕様を記述できます。サンプルは以下です。

```python
import argparse
def func(args):
    return sum(args)
parser = argparse.ArgumentParser(description='Process some integers.')
# 複数の種類なら nargsは固定に, 任意の長さのものを複数取ると,前に集約される
parser.add_argument('dorararara', metavar='Crazy Diamond', type=int, nargs='+',
                    help='an integer for the accumulator') # 受け取り
parser.add_argument('--DIO', dest='UNKNOWN', action='store_const',
                    const=func, default=max,
                    help='sum the integers (default: find the max)')
parser.add_argument('--wd', default=40536, type=int) # default
args = parser.parse_args()
parser.print_help() # helpのprint
print(args.UNKNOWN(args.dorararara)) # 計算結果
print("FE -",args.wd)
# python3 tmp.py 1 2 3 4 --DIO --wd 40536
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417525/ac779458-258c-2463-af15-4d36b47a57ef.png)
(https://docs.python.org/ja/3/library/argparse.html#the-add-argument-method より)

ここで,私個人的に思ったのが,const(ant)とdefaultが同じような意味合いを持っている感触だったので見分けが多少覚えづらいなと思いました。

# 2. [Decorator](https://docs.python.org/ja/3/glossary.html#term-decorator)

公式documentにある通り,wrapper構文で書かれるのが一般的です。
試しにwrapper構文以外で書くと,定義をするだけで下記のコードはprintされてしましました。

```python
def Vs_Dio(who):
    for _ in range(2):
        print("Mudamudamudamuda")
        who()
@Vs_Dio
def Jotaro(*args, **kwargs):
    print("Oraoraoraora")
print("-"*50)
def vs_dio(who):
    def wrapper(*args, **kwargs):
        for _ in range(2):
            print("muda"*3)
            who()
    return wrapper
@vs_dio
def jotaro(*args, **kwargs):
    print("ora"*3)
jotaro()
```

# 3. Method [Static](https://docs.python.org/ja/3.8/library/functions.html#staticmethod) v.s. [Class](https://docs.python.org/ja/3.8/library/functions.html#classmethod)
簡単に言えば,classは引数にclassを, staticは引数を必要としません。

```python
class Nen:
    def __init__(self,type_p) -> None:
        self.type_p=type_p
    @classmethod
    def syugyo(cls):
        GON=cls("POWER")
        return GON
    @staticmethod
    def mizumishiki(s):
        if s=="POWER":
            return "OVER"
        else:
            return "NO-OVER"
gon=Nen.syugyo()
kirua=Nen("NO-POWER")
print(Nen.mizumishiki(gon.type_p))
print(getattr(gon,"type_p"))
print(Nen.mizumishiki(kirua.type_p))
print(getattr(kirua,"type_p"))
setattr(kirua,"type_p","POWER")
print(Nen.mizumishiki(kirua.type_p))
```

# 4. [property , setter](https://docs.python.org/ja/3/library/functions.html#property)

これは,クラスの値のsetやgetを明示的に定義できるようになります。

```python
from sys import argv, flags
flag=argv[1]=="t"
class Git():
    def __init__(self, name, password) -> None:
        self.name=name
        self.__password=password # name, mangling
    @property
    def password(self):
        return self.__password
    if flag:
        @password.setter
        def password(self, value):
            print("setter")
            self.__password=value
boku=Git("ma", "1234password")
print(boku._Git__password)
if flag:
    boku.password="chon"
else:
    boku._Git__password="chon"
print(boku.password)
```

# 5. [Union](https://docs.python.org/ja/3/library/typing.html#typing.Union)

unionは公式docsそのままです

```python
from typing import Union, List
import numpy as np
def get_len_1(lst:Union[List, np.ndarray]) -> int:
    print(len(list(lst)))
get_len_1([1,2,3])
get_len_1(np.array([[1,2,3]]))
```

# 6. [yield](https://docs.python.org/ja/3/reference/expressions.html?highlight=yield#yield-expressions)

generatorを作成するために使用します。

```python
from typing import Generator
def my_gene(a: int) -> Generator:
    c=0
    while(c<a):
        yield (c+10)*2**c
        c+=1
for x in my_gene(10):
    print(x)
```


# 7. [with](https://docs.python.org/ja/3/reference/compound_stmts.html#the-with-statement)

ブロックの実行を、コンテキストマネージャによって定義されたメソッドでラップするために使われる。
そのため,デコレータのように扱うことができようなケースも多い。

```python
import contextlib
class A:
    def __init__(self,value) -> None:
        self.value=value
tmp=A(3)

@contextlib.contextmanager
def func(a:int) -> None:
    old_value=getattr(tmp, "value")# 前処理
    setattr(tmp,"value",old_value+a)
    try:
        yield
    finally:
        setattr(tmp,"value",old_value)# 終了後

with func(100):
    print(tmp.value)
print(tmp.value)

print("-"*20)

@func(200)
def ora():
    print(tmp.value)

ora()
print(tmp.value)
```

一般的にopenなどでよく使われる.
参考記事
- [【Python】with構文を１分で解説―with open/ファイル操作―](https://it-biz.online/python/with/)
- [Pythonの関数デコレータでopenしてcloseする](https://shtaxxx.hatenablog.com/entry/20111126/1322315945)


# 追記

- torchの[stack](https://pytorch.org/docs/stable/generated/torch.stack.html)

これに関しては立方体を書いていただくと理解しやすいかと思います。

```python
import torch
lst=torch.tensor([[1,2,3],[4,5,6]])
lst_s=[lst,torch.add(lst,100),torch.add(lst,200)]
for i in range(len(lst_s)):
    tmp=torch.stack(lst_s,dim=i)
    print(tmp.shape)
    print(tmp)
"""
torch.Size([3, 2, 3])
tensor([[[  1,   2,   3],
         [  4,   5,   6]],

        [[101, 102, 103],
         [104, 105, 106]],

        [[201, 202, 203],
         [204, 205, 206]]])
torch.Size([2, 3, 3])
tensor([[[  1,   2,   3],
         [101, 102, 103],
         [201, 202, 203]],

        [[  4,   5,   6],
         [104, 105, 106],
         [204, 205, 206]]])
torch.Size([2, 3, 3])
tensor([[[  1, 101, 201],
         [  2, 102, 202],
         [  3, 103, 203]],

        [[  4, 104, 204],
         [  5, 105, 205],
         [  6, 106, 206]]])
"""
```

- [ABC](https://docs.python.org/ja/3/library/abc.html)というかクラス全体

selfなどで指定しなくても,selfで指定されるみたいです.

```python
from abc import ABC
from typing import List

class EEE(ABC):
    callbacks: List[int] = [1,2,3,4555]

class De(EEE):
    nai=[0,0,0]
    def __init__(self) -> None:
        super().__init__()
        self.call=[1,2,3]
        print(self.callbacks)
        print(self.nai)

yo=De()
"""
[1, 2, 3, 4555]
[0, 0, 0]
"""
```


# 終わりに
他にもたくさん知らないことがあるため,都度都度キャッチアップをしたいと感じました。また,自作でライブラリを作る場合はこの辺りの知識は非常に重要であると同時に,正しくライブラリを理解するためにもこの辺りの知識が非常に重要であると感じました。


次回の予定 : [torch/autograd/grad_mode.pyのgithub](https://github.com/pytorch/pytorch/blob/master/torch/autograd/grad_mode.py)を理解します。