3

関数に渡されたときのローカル変数名を知りたいです。これが可能かどうかはまったくわかりません。この例を考えてみましょう:

関数定義:

def show(x):
  print(x)

利用方法:

a = 10
show(a)

これは 10 を出力します。しかし、私は "a = 10" を出力するのが好きです。これはpythonで可能ですか?

4

7 に答える 7

7

正確にはこのようではありません。ただし、同様のことを実現できます。

def show(**kwargs):
  print(', '.join('%s=%s' % kv for kv in kwargs.items()))

show(a=20)
于 2012-12-11T20:03:34.530 に答える
5

いいえ、関数に値を渡すために使用されるローカル変数の名前を知ることはできません。

いずれにせよ、これは不可能な作業です。次の例の変数名は何でしょうか?

arguments = ('a', 1, 10)
somefunction(*(arguments[:2] + [10]))

ここでは、3つの引数を渡します。2つは前に定義したタプルから取得し、1つはリテラル値であり、3つすべてが可変引数リスト構文を使用して渡されます。

于 2012-12-11T20:02:16.153 に答える
3

次の解決策がいくつかの批判を受けることを予言します

def show(*x):
    for el in x:
        fl = None
        for gname,gobj in globals().iteritems():
            if el==gobj:
                print '%s == %r' % (gname,el)
                fl = True
        if not fl:
            print 'There is no identifier assigned to %r in the global namespace' % el

un = 1
y = 'a'
a = 12
b = c = 45
arguments = ('a', 1, 10)
lolo = [45,'a',a,'heat']

print '============================================'
show(12)
show(a)
print '============================================'
show(45)
print
show(b)
print '============================================'
show(arguments)
print
show(('a', 1, 10))
print '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'
show(*arguments)
print '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'
show(*(arguments[1:3] + (b,)))

結果

============================================
a == 12
a == 12
============================================
c == 45
b == 45

c == 45
b == 45
============================================
arguments == ('a', 1, 10)

arguments == ('a', 1, 10)
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
y == 'a'
un == 1
There is no identifier assigned to 10 in the global namespace
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
un == 1
There is no identifier assigned to 10 in the global namespace
c == 45
b == 45
于 2012-12-12T00:24:44.853 に答える
3

Fredrik Lundh を引用して、Python プログラミング FAQ にあるこの質問への回答が気に入っています。

玄関先で見つけた猫の名前を知るのと同じように、猫 (オブジェクト) 自体はその名前を伝えることができず、特に気にもしていません。そのため、その名前を知る唯一の方法は、猫(オブジェクト)の場合、すべての隣人(名前空間)...

....多くの名前で知られていたり、まったく名前がなくても驚かないでください!

于 2012-12-11T20:09:53.303 に答える
1

Python では不可能に思えますが、C++ では実際に可能です。

#define show(x)   std::cout << #x << " = " << x << std::endl
于 2013-01-31T05:35:04.847 に答える
1

を使用した新しいソリューションreadline

インタラクティブなセッションに参加している場合、通常は機能する非常に単純なソリューションを次に示します。

def show(x):
    from readline import get_current_history_length, get_history_item
    print(get_history_item(get_current_history_length()).strip()[5:-1] + ' = ' + str(x))

インタラクティブセッションバッファの最後の行入力を読み取り、先頭または末尾の空白を削除してから、最初の 5 文字 (できればshow() と最後の文字 (できれば)) 以外のすべてを提供するだけで、渡されたものは何でも残ります。 .

例:

>>> a = 10
>>> show(a)
a = 10
>>> b = 10
>>> show(b)
b = 10
>>> show(10)
10 = 10
>>> show([10]*10)
[10]*10 = [10, 10, 10, 10, 10, 10, 10, 10, 10, 10]
>>> show('Hello' + 'World'.rjust(10))
'Hello' + 'World'.rjust(10) = Hello     World

付属の Python のバージョンを使用して OS X を使用しているreadline場合、デフォルトではインストールされていませんが、 pip. あなたがWindowsを使用している場合、あなたには存在しません... fromreadlineを使用できるかもしれませんが、私は試したことがないので、それが許容できる代替品であるかどうかはわかりません.pyreadlinepip

上記のコードをより防弾にすることは、読者の演習として残しておきます。考慮すべきことは、次のようなものを処理する方法です。

show(show(show(10)))
show(
10
)

この種のものにスクリプトからの変数名を表示させたい場合は、inspect を使用して呼び出しフレームのソース コードを取得することを検討できます。しかし、スクリプトで使用したい理由や、上記のように意図的に機能を台無しにする人々を処理するためだけに機能を複雑にする理由が思いつかないのでshow()、今考えている時間を無駄にするつもりはありませんそれを出します。

を使用した元のソリューションinspect

これは私の元のソリューションです。これはより複雑で、より明白な一連の警告がありますがinspect、 ではなくのみを使用するreadlineため、より移植性が高く、すべてのプラットフォームで実行され、対話型セッションまたはスクリプトのどちらにいるかに関係なく実行されます。

def show(x):

    from inspect import currentframe

    # Using inspect, figure out what the calling environment looked like by merging
    #   what was available from builtin, globals, and locals.
    # Do it in this order to emulate shadowing variables
    #   (locals shadow globals shadow builtins).

    callingFrame = currentframe().f_back
    callingEnv = callingFrame.f_builtins.copy()
    callingEnv.update(callingFrame.f_globals)
    callingEnv.update(callingFrame.f_locals)

    # Get the variables in the calling environment equal to what was passed in.
    possibleRoots = [item[0] for item in callingEnv.items() if item[1] == x]

    # If there are none, whatever you were given was more than just an identifier.
    if not possibleRoots:
        root = '<unnamed>'
    else:
        # If there is exactly one identifier equal to it,
        #   that's probably the one you want.
        # This assumption could be wrong - you may have been given
        #   something more than just an identifier.
        if len(possibleRoots) == 1:
            root = str(possibleRoots[0])
        else:
            # More than one possibility? List them all.
            # Again, though, it could actually be unnamed.
            root = '<'
            for possibleRoot in possibleRoots[:-1]:
                root += str(possibleRoot) + ', '
            root += 'or ' + str(possibleRoots[-1]) + '>'

    print(root + ' = ' + str(x))

これが完全に機能するケースです(質問からのもの):

>>> a = 10
>>> show(a)
a = 10

別の楽しいケースを次に示します。

>>> show(quit)
quit = Use quit() or Ctrl-Z plus Return to exit

これで、その機能が Python インタープリターでどのように実装されたかがわかりました。これは、適切に終了する方法をquit示す の組み込み識別子です。str

希望よりも少ない場合がいくつかありますが、... 許容範囲ですか?

>>> b = 10
>>> show(b)
<a, or b> = 10
>>> show(11)
<unnamed> = 11
>>> show([a])
<unnamed> = [10]

そして、これは真のステートメントを出力するケースですが、あなたが探していたものではないことは間違いありません:

>>> show(10)
<a, or b> = 10
于 2015-02-20T17:38:42.353 に答える
-1

f-stringsを使用したPython 3.6の時点でのみ可能になった答えは次のとおりです。

x = 10
print(f'{x=}')  # Outputs x=10
于 2021-02-20T03:21:08.710 に答える