python変数名の印刷

5789 ワード

aa = 1
print(aa)

出力結果:
1

printを使用して変数を簡単に印刷する場合、変数名に対応する値しか表示されず、変数名は印刷されませんが、どうすれば変数名を印刷できますか?
pythonにlocals()を内蔵することは、変数名を印刷する鍵です.
aa = 1
print(locals())

出力結果:
{..., 'aa': 1, '__name__': '__main__', '__spec__': None,...}  

変数aaの名前がこの辞書に保存されていることがわかりますので、辞書の値が変数aaが指す値と同じ値であるかどうかを一つ一つチェックすることで変数名を得ることができます.
def var_name(var,all_var=locals()):
    return [var_name for var_name in all_var if all_var[var_name] is var][0]

aa = 11
bb = 22
cc = 33
dd = 44
print(var_name(aa))
print(var_name(bb))
print(var_name(cc))
print(var_name(dd))

出力結果:
aa
bb
cc
dd

関数ヘッダにはlocals()をデフォルトパラメータとして使用し,得られた辞書は外部の局所変数パラメータ辞書である(新しい発見,ねえへへ).
しかし、複数の変数名が同じ値を指すと、名前を間違えて混乱させるという問題がある.
def var_name(var, all_var=locals()):
    return [var_name for var_name in all_var if all_var[var_name] is var][0]


aa = bb = 11
cc = dd = 22
print(var_name(aa))
print(var_name(bb))
print(var_name(cc))
print(var_name(dd))

出力結果:
bb
bb
cc
cc

したがって、変数の値が一度だけ参照される場合にのみ使用できます.
究極の解決策
stackoverflowで見つけた答え
import inspect, re

def varname(p):
  for line in inspect.getframeinfo(inspect.currentframe().f_back)[3]:
    m = re.search(r'\bvarname\s*\(\s*([A-Za-z_][A-Za-z0-9_]*)\s*\)', line)
    if m:
      return m.group(1)


spam = 42
print(varname(spam))

出力結果:
spam

原理:varnameを呼び出す行のコードの文字列をチェックすることで変数名を得る.
参考資料:stackoverflowでの解決方法