1
1

More than 1 year has passed since last update.

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

Last updated at Posted at 2021-11-30

はじめに

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

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

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

次回 : torch/autograd/grad_mode.pyのgithubを理解します。

1. argparse

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

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://docs.python.org/ja/3/library/argparse.html#the-add-argument-method より)

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

2. Decorator

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

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 v.s. Class

簡単に言えば,classは引数にclassを, staticは引数を必要としません。

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

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

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

unionは公式docsそのままです

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

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

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

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

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構文を1分で解説―with open/ファイル操作―
- Pythonの関数デコレータでopenしてcloseする

追記

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

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というかクラス全体

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

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を理解します。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1