LoginSignup
1
2

More than 3 years have passed since last update.

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

Last updated at Posted at 2019-10-15

初めに

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

環境

Python 3.7.3

概要

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

完成品

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'>

実行スクリプト

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

おわりに

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

1
2
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
2