Pythonで関数の引数と返却値の型を明示したい

#初めに
　好きな言語だからといってその言語のあらゆる仕様が許せる人間は少数派でしょう。自分はPythonに対して可視性やオブジェクトの扱いで多少の不満があったりなかったりします。
　その中でもPythonを勉強し始めてまず初めに思ったことが、「何で関数の引数・返却値の明示が出来ないのだろう」と思いました。なので作りました。
※この記事は暇を持て余した、C・Javaに囚われながらPythonの寛容さに流された哀れな人間のお遊びです。

#環境
 Python 3.7.3

#概要
　1. まず指定された書式の文字列で引数と返却値を指定する。
　2. 引数・返却値の型をtype関数で調べて指定されたものだったら特に通知しない。
　3. もし指定されていないものだったら`RuntimeError`を送り出す。

#完成品
```Python:CheckValue.py
class CheckValue():
    """This module make appointed argument and return value in user function.
    Usage: from CheckValue import CheckValue
           Initialize Class -> CheckValue(SpecifyExpression :str)
            ex -> CheckValue("int, str, __main__.ClassObject -> NoneType")
           Check Argument -> 1. First argument of applied function specify this object.
                             2. Call cArg method in CheckValue 
                                and this argument is to make tuple object all of not first argument.
            ex -> def(CheckValue, num, msg, object): CheckValue.cArg((num, msg, object))
           Check Return Value  -> Call cRet method in CheckValue and return this.
            ex -> return CheckValue.cRet(return_value)
           If Error Value Type -> Raise RuntimeError: Input_Argument_Type:<class 'type'> Appoint_Input_Value_Type:<class 'another_type'>
                                                      Output_Value_Type:<class 'type'>" Appoint_Input_Value_Type:<class 'another_type'>
            ex -> RuntimeError: Input_Argument_Type:<class 'int'> Appoint_Input_Value_Type:<class 'str'>
    
    def function(CheckValue, num, msg, object):
        CheckValue.cArg((num, msg, object))
        #Any Processing
        return CheckValue.cRet(return_value)
    
    some_value = function(CheckValue("int, str, __main__.ClassObject -> NoneType"), 3, "foo", object)
    """
    def __init__(self, arg_ret):
        if("->" not in arg_ret):
            raise RuntimeError("Not found arrow:->.")
        self.appoint_arg = [e.strip() for e in arg_ret.split("->")[0].split(",")]
        self.appoint_ret = arg_ret.split("->")[1].strip()
    def cArg(self, in_var):
        for e_aa, e_ia in zip(self.appoint_arg, in_var):
            if str(type(e_ia)) != f"<class '{e_aa}'>":
                raise RuntimeError(f"Input_Argument_Type:{str(type(e_ia))} Appoint_Input_Value_Type:<class '{e_aa}'>")
    def cRet(self, out_var):
        if str(type(out_var)) != f"<class '{self.appoint_ret}'>":
            raise RuntimeError(f"Output_Value_Type:{str(type(out_var))} Appoint_Return_Value_Type:<class '{self.appoint_ret}'>")
        return out_var
```

#使用法(docで言いたいこと)
このモジュールはユーザー作成の関数の引数と返却値の型を指定するものです。
使用法 `from CheckValue import CheckValue`
クラスの初期化 `CheckValue(SpecifyExpression :str)`
 <例> `CheckValue("int, str, __main__.ClassObject -> NonType")`
引数の型の確認 `型チェックしたい関数の初めの引数にこのオブジェクトを指定する。`
`その関数の引数のCheckValue以外の引数をtupleにいれてcArgを呼び出す。`
 <例> `def(CheckValue, num, msg, object): CheckValue.cArg((num, msg, object))`
返却値の確認 `cRetメソッドを呼び出し、それ自体を返却する。`
 <例> `return CheckValue.cRet(return_value)`
エラーがあった時 `RuntimeErrorが送り出されます。`
 <例> `RuntimeError: Input_Argument_Type:<class 'int'> Appoint_Input_Value_Type:<class 'str'>`

#実行スクリプト
```Python:main.py
from CheckValue import CheckValue as cv

def greet(cv, msg, n):
    cv.cArg((msg, n))
    print(msg * n)
    return cv.Ret(None)

ans = greet(cv("str, int -> NoneType"), "hello", 3)
#hellohellohello
```

#おわりに
　明示するというよりは引数が上手く合った時そのように扱うという感じです。詰めが甘いところがあるので気が向いたらまた直します。暇な人は適当に改造してくれ。ところで型アノテーションは使っちゃいけない縛りでもしてるんですかね私は。