7

Pythonに変数xがあります。変数から文字列「x」を見つけるにはどうすればよいですか。これが私の試みです:

def var(v,c):
  for key in c.keys():
    if c[key] == v:
      return key


def f():
  x = '321'
  print 'Local var %s = %s'%(var(x,locals()),x)  

x = '123'
print 'Global var %s = %s'%(var(x,locals()),x)
f()

結果は次のとおりです。

Global var x = 123
Local var x = 321

上記のレシピは少し非Python風のようです。同じ結果を達成するためのより良い/より短い方法はありますか?

4

4 に答える 4

14

Q:Pythonに変数xがあります。変数から文字列「x」を見つけるにはどうすればよいですか。

A:私があなたの質問を正しく理解しているなら、あなたは変数の値からその名前に行きたいと思うでしょう。これはPythonでは実際には不可能です。

Pythonには、実際には「変数」のようなものはありません。Pythonが実際に持っているのは、オブジェクトをバインドできる「名前」です。オブジェクトにバインドされている可能性のある名前があれば、それはオブジェクトに違いはありません。何十もの異なる名前にバインドされているか、まったくバインドされていない可能性があります。

この例を考えてみましょう。

foo = 1
bar = foo
baz = foo

ここで、値が1の整数オブジェクトがあり、逆方向に作業してその名前を見つけたいとします。何を印刷しますか?3つの異なる名前には、そのオブジェクトがバインドされており、すべて同じように有効です。

print(bar is foo) # prints True
print(baz is foo) # prints True

Pythonでは、名前はオブジェクトにアクセスする方法であるため、名前を直接操作する方法はありません。検索しlocals()て値を見つけて名前を復元できる場合もありますが、それはせいぜいパーラーのトリックです。そして、私の上記の例では、、、、fooのどれが「正しい」答えですか?それらはすべてまったく同じオブジェクトを参照します。barbaz

PS上記は、私が以前に書いた回答のいくらか編集されたバージョンです。 今回は言葉遣いの方が上手くいったと思います。

于 2009-11-03T08:15:11.807 に答える
7

私はあなたが望むものの一般的な形はオブジェクトrepr()の方法であると信じています。__repr__()

に関して__repr__()

repr()組み込み関数および文字列変換(逆引用符)によって呼び出され、オブジェクトの「公式」文字列表現を計算します。

こちらのドキュメントを参照してください:オブジェクト。repr(自己)

于 2009-11-03T07:58:17.397 に答える
3

stevenhaはこの質問に対する素晴らしい答えを持っています。ただし、とにかく名前空間ディクショナリを実際に調べたい場合は、次のように特定のスコープ/名前空間で特定の値のすべての名前を取得できます。

def foo1():
    x = 5
    y = 4
    z = x
    print names_of1(x, locals())

def names_of1(var, callers_namespace):
    return [name for (name, value) in callers_namespace.iteritems() if var is value]

foo1() # prints ['x', 'z']

スタックフレームをサポートしているPythonを使用している場合(ほとんどの場合、CPythonはサポートしています)、ローカルのdictをnames_of関数に渡す必要はありません。関数は、呼び出し元のフレーム自体からその辞書を取得できます。

def foo2():
    xx = object()
    yy = object()
    zz = xx
    print names_of2(xx)

def names_of2(var):
    import inspect
    callers_namespace = inspect.currentframe().f_back.f_locals
    return [name for (name, value) in callers_namespace.iteritems() if var is value]

foo2() # ['xx', 'zz']

名前属性を割り当てることができる値型を使用している場合は、それに名前を付けてから、次のように使用できます。

class SomeClass(object):
    pass

obj = SomeClass()
obj.name = 'obj'


class NamedInt(int):
    __slots__ = ['name']

x = NamedInt(321)
x.name = 'x'

最後に、クラス属性を操作していて、それらの名前を知ってもらいたい場合(記述子は明らかなユースケースです)、DjangoORMおよびSQLAlchemy宣言型テーブル定義で行うようにメタクラスプログラミングでクールなトリックを行うことができます。

class AutonamingType(type):
    def __init__(cls, name, bases, attrs):
        for (attrname, attrvalue) in attrs.iteritems():
            if getattr(attrvalue, '__autoname__', False):
                attrvalue.name = attrname
        super(AutonamingType,cls).__init__(name, bases, attrs)

class NamedDescriptor(object):
    __autoname__ = True
    name = None
    def __get__(self, instance, instance_type):
        return self.name

class Foo(object):
    __metaclass__ = AutonamingType

    bar = NamedDescriptor()
    baaz = NamedDescriptor()

lilfoo = Foo()
print lilfoo.bar   # prints 'bar'
print lilfoo.baaz  # prints 'baaz'
于 2009-11-03T16:20:21.463 に答える
1

Pythonでオブジェクトの「the」文字列表現を取得する方法は3つあります。1:str()

>>> foo={"a":"z","b":"y"}
>>> str(foo)
"{'a': 'z', 'b': 'y'}"

2:repr()

>>> foo={"a":"z","b":"y"}
>>> repr(foo)
"{'a': 'z', 'b': 'y'}"

3:文字列補間:

>>> foo={"a":"z","b":"y"}
>>> "%s" % (foo,)
"{'a': 'z', 'b': 'y'}"

この場合、3つのメソッドすべてが同じ出力を生成しましたが、違いは、str()がを呼び出しdict.__str__()、repr()がを呼び出すことdict.__repr__()です。str()は文字列補間で使用されますが、repr()は、リストまたはdictを出力するときに、リストまたはdictの各オブジェクトでPythonによって内部的に使用されます。

Tendayi Mawusheが前述したように、reprによって生成された文字列は、必ずしも人間が読める形式であるとは限りません。

また、のデフォルトの実装.__str__()はを呼び出す.__repr__()ことであるため、クラスに独自のオーバーライドがない場合は、.__str__()から返された値.__repr__()が使用されます。

于 2009-11-03T10:09:00.503 に答える