关于representation:如何在Python中获得变量的字符串表示?

How do I get the string representation of a variable in python?

我在python中有一个变量x。如何从变量中找到字符串"x"。这是我的尝试:

1
2
3
4
5
6
7
8
9
10
11
12
13
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()

结果是:

1
2
Global var x = 123
Local var x = 321

上面的食谱似乎有点不派头。是否有更好/更短的方法来实现相同的结果?


问:我在python中有一个变量x。如何从变量中找到字符串"x"。

答:如果我正确理解了你的问题,你需要从变量的值转到它的名称。这在Python中是不可能的。

在Python中,实际上没有"变量"这样的东西。python真正拥有的是"名称",可以将对象绑定到它们上。它与对象没有任何区别,它可能绑定到的名称(如果有)。它可能绑定到几十个不同的名称,或者没有。

考虑这个例子:

1
2
3
foo = 1
bar = foo
baz = foo

现在,假设您有一个值为1的整型对象,您希望向后工作并找到它的名称。你要打印什么?三个不同的名称都将该对象绑定到它们上,并且所有名称都同样有效。

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

在Python中,名称是访问对象的一种方式,因此无法直接使用名称。你也许可以搜索locals(),找到这个值并恢复一个名字,但这充其量只是一个客厅的把戏。在我上面的例子中,哪个是"正确"的答案?它们都指向完全相同的对象。

P.S.以上是我以前写的答案的一个经过编辑的版本。我想这次我在措辞方面做得更好。


我相信你想要的一般形式是对象的repr()__repr__()方法。

关于__repr__()

Called by the repr() built-in function
and by string conversions (reverse
quotes) to compute the"official"
string representation of an object.

在此处查看文档:object.repr(self)


stevenha has a great answer to this question. But, if you actually do want to poke around in the namespace dictionaries anyway, you can get all the names for a given value in a particular scope / namespace like this:

1
2
3
4
5
6
7
8
9
10
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(大多数情况下支持堆栈帧),则不需要将locals dict传递到names_of函数中;该函数可以从调用方的帧本身检索字典:

1
2
3
4
5
6
7
8
9
10
11
12
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']

如果您使用的是可以为其分配名称属性的值类型,则可以为其指定名称,然后使用该名称:

1
2
3
4
5
6
7
8
9
10
11
12
class SomeClass(object):
    pass

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


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

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

最后,如果您使用的是类属性,并且希望它们知道它们的名称(描述符是明显的用例),那么您可以像在django orm和sqlacalchemy声明性样式表定义中那样,对元类编程做一些很酷的技巧:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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'

在python中,有三种方法可以获得对象的"字符串"表示:1:()

[cc lang="python"]>>> foo={"a":"z","b":"y