LoginSignup
43
34

More than 5 years have passed since last update.

printデバッグに最適! pythonで変数名を文字列にして、中の値と同時にprintする関数を実装

Last updated at Posted at 2017-06-06

printデバッグをpythonで行う場合、以下のように書くことが多いのではないだろうか。

print("hoge = " + str(hoge))

しかしわざわざダブルクォーテーションで囲ったりstr()を用いたりするのは面倒である。
そこで、pythonインターフェースを開いたら、以下のようなchkprint関数を記述しておくと良い。

1. 実装

def chkprint(*args):
    flg = 1
    for obj in args:
        for k, v in globals().items():
            if id(v) == id(obj):
                target = k
                break
        if flg == 1:
            out = target+' = '+str(obj)
            flg = 0
        else:
            out += ', '+target+' = '+str(obj)            
    print(out)

この関数を一番最初に定義しておくだけ。

(※2017/06/07追記 : 上記の関数はグローバル変数にしか対応していません。shiracamusさんのコメントに書かれている関数がローカル変数にも対応しているので、ここに記載します)

from inspect import currentframe

def chkprint(*args):
    names = {id(v):k for k,v in currentframe().f_back.f_locals.items()}
    print(', '.join(names.get(id(arg),'???')+' = '+repr(arg) for arg in args))

2. 挙動

def chkprint(*args):
    flg = 1
    for obj in args:
        for k, v in globals().items():
            if id(v) == id(obj):
                target = k
                break
        if flg == 1:
            out = target+' = '+str(obj)
            flg = 0
        else:
            out += ', '+target+' = '+str(obj)            
    print(out)


if __name__=="__main__":
    a = 1
    lst = [3, 1, 4, 1, 5]
    chkprint(a)
    chkprint(lst)
    chkprint(a, lst)
実行結果
a = 1
lst = [3, 1, 4, 1, 5]
a = 1, lst = [3, 1, 4, 1, 5]

こんな感じになる。
長いコードを動かしている途中でprintデバッグをはさみたくなった時、このchkprint関数は手軽に「変数名」と「その変数の中身」を同時にprintしてくれるので、とても便利であると思われる。

3. 詳細

上記の関数で、一体何をやっているのかの説明。

for k, v in globals().items():
    if id(v) == id(obj):
        target = k
        break

この部分はすべて、変数obj"obj"という文字列に変換するためのものである。
globals()とは、グローバル変数の一覧を辞書として返す「組み込み関数」である。

>>> globals()
{ '__name__': '__main__', 'a': 1, 'lst': [3, 1, 4, 1, 5], '__package__': None, 
'__builtins__': <module 'builtins' (built-in)>, '__doc__': None, '__spec__': None}

この中でvidobjidと一致した場合には、その時のkの値が変数名の文字列、ということになる。
(id()を付けているのは、「中の値はobjと同じだけれども変数名はobjと異なるような変数」が拾われてしまうのを避けるためである)

参考URL

43
34
5

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
43
34