[解決済み】変数名を文字列で取得する方法
質問
このスレッドでは、Pythonで関数の名前を文字列として取得する方法について説明します。 関数名を文字列として取得する方法は?
変数に対して同じことをするにはどうすればよいですか?関数とは対照的に、Pythonの変数には
__name__
属性があります。
つまり、次のような変数があった場合。
foo = dict()
foo['bar'] = 2
私は関数/属性を探しています、例えば
retrieve_name()
にするために
このリストからPandasでDataFrameを作成します。
ここで
列名
は、実際の辞書の名前で与えられる。
# List of dictionaries for my DataFrame
list_of_dicts = [n_jobs, users, queues, priorities]
columns = [retrieve_name(d) for d in list_of_dicts]
解決方法は?
TL;DR
を使用します。
Wrapper
ヘルパーは
python-varname
:
from varname.helpers import Wrapper
foo = Wrapper(dict())
# foo.name == 'foo'
# foo.value == {}
foo.value['bar'] = 2
リスト内包の部分は、こうすればいい。
n_jobs = Wrapper(<original_value>)
users = Wrapper(<original_value>)
queues = Wrapper(<original_value>)
priorities = Wrapper(<original_value>)
list_of_dicts = [n_jobs, users, queues, priorities]
columns = [d.name for d in list_of_dicts]
# ['n_jobs', 'users', 'queues', 'priorities']
# REMEMBER that you have to access the <original_value> by d.value
の作者です。
python-varname
パッケージで提供されます。ご不明な点がありましたら、ご連絡ください。
長い答え
それは可能なのか?
YesとNoです。
実行時に変数名を取得するため、前のフレームにアクセスして変数名を取得できるような関数が必要です。そのために
Wrapper
そこで その関数では、実行時に、前のフレームのソースコード/ASTノードを解析して、正確な変数名を取得しています。
しかし、前のフレームにあるソースコード/ASTノードが常に利用できるとは限りませんし、他の環境によって変更されている可能性もあります(例えば
pytest
's
assert
ステートメント)。簡単な例としては、コードが
exec()
. それでもバイトコードから何らかの情報を取り出すことはできますが、手間がかかりすぎるし、エラーが発生しやすくなります。
どうすればいい?
まず、変数がどのフレームに与えられているかを特定する必要があります。単純に直前のフレームとは限りません。例えば、関数のラッパーが別にある場合もあります。
from varname import varname
def func():
return varname()
def wrapped():
return func()
x = wrapped()
上記の例では、フレームをスキップして
wrapped
正しいフレームに到達するために
x = wrapped()
の位置を特定できるように
x
. 引数
frame
と
ignore
の
varname
を使えば、これらの中間フレームのいくつかをスキップすることができます。詳しくはREADMEファイルやパッケージのAPIドキュメントをご覧ください。
次に、ASTノードを解析して、変数に値が割り当てられている(関数呼び出し)場所を特定する必要があります。単純な代入とは限りません。時には、例えば、複雑なASTノードが存在する可能性もあります。
x = [wrapped()]
. ASTツリーを走査して、正しい割り当てを特定する必要がある。
信頼性は?
割り当てノードを特定すれば、それは信頼できるものです。
varname
はすべて
executing
パッケージでノードを探します。実行時に検出されるノードは正しいものであることが保証されます (
これ
).
pytest, ipython, macropy, birdseye, reticulate with Rなど、他のASTマジックが適用される環境でも部分的に動作します。executingもvarnameもそれらの環境では100%動作しません。
パッケージが必要なのか?
さて、イエスとノー、もう一度。
シナリオが単純であれば、@juan Isaza や @scohe001 が提供しているコードで、直前のフレームで変数が定義されていて、AST ノードが単純な代入であるようなケースでは、おそらく十分に動作すると思われます。1フレーム前に戻って、そこで情報を取得すればいいだけです。
しかし、シナリオが複雑になったり、異なるアプリケーションシナリオを採用する必要がある場合、おそらく以下のようなパッケージが必要になります。
python-varname
を、処理することができます。これらのシナリオは、に含まれるかもしれません。
- ソースコードが利用できない場合やASTノードにアクセスできない場合に、より親切なメッセージを表示します。
- 中間フレームをスキップする(他の中間フレームで関数をラップしたり呼び出したりすることができる)
-
は、組み込み関数やライブラリからの呼び出しを自動的に無視します。例えば
x = str(func())
- 代入の左側にある複数の変数名を取得する
- その他
はどうでしょうか。
f-string
?
Aivar Paalbergが提供した答えのように。確かに高速で信頼性が高いです。しかし、これは実行時ではなく、つまり、それが
foo
を出力する前に、その名前を出力してください。しかし
varname
を使えば、その変数が来ることを知らなくてもいいのです。
from varname import varname
def func():
return varname()
# In external uses
x = func() # 'x'
y = func() # 'y'
最後に
python-varname
は、代入から変数名を検出できるだけでなく。
-
変数名を直接取得するには
nameof
-
次の直属の属性名を検出します。
will
-
関数に渡された引数名/ソースを取得するには、次のようにします。
argname
詳しくはドキュメントをご覧ください。
しかし、最後に言いたいのは、そのことです。 なるべく使わないようにしましょう。
なぜなら、クライアントコードがソースノードが利用可能な環境、あるいはASTノードにアクセス可能な環境で実行されるかどうかは、確認できないからです。そしてもちろん、ソースコードを解析し、環境を特定し、ASTノードを取得し、必要なときにそれを評価するためにはリソースがかかります。
関連
-
[解決済み] データ型が理解できない
-
[解決済み】NameError: 名前 'self' が定義されていません。
-
[解決済み] for'ループでインデックスにアクセスする?
-
[解決済み] Pythonには文字列の'contains'サブストリングメソッドがありますか?
-
[解決済み] バイトを文字列に変換する
-
[解決済み] モジュールの関数名(文字列)を使って、モジュールの関数を呼び出す。
-
[解決済み] インスタンスのクラス名を取得する?
-
[解決済み] 最近のPythonでカスタム例外を宣言する適切な方法?
-
[解決済み] 関数名を文字列として取得するには?
-
[解決済み】Pandas DataFrameのカラムヘッダからリストを取得する。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
PythonによるLeNetネットワークモデルの学習と予測
-
Evidentlyを用いたPythonデータマイニングによる機械学習モデルダッシュボードの作成
-
pyCaret効率化乗算器 オープンソース ローコード Python機械学習ツール
-
Pythonショートビデオクローラーチュートリアル
-
[解決済み】RuntimeWarning: 割り算で無効な値が発生しました。
-
[解決済み】Pythonスクリプトで「Expected 2D array, got 1D array instead: 」というエラーが発生?
-
[解決済み】 NameError: グローバル名 'xrange' は Python 3 で定義されていません。
-
[解決済み】Python elifの構文が無効です【終了しました
-
[解決済み】SyntaxError: デフォルト以外の引数がデフォルトの引数に続く
-
[解決済み] TypeError: 'DataFrame' オブジェクトは呼び出し可能ではない