繁体   English   中英

如何在python中获取变量的字符串表示?

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

我在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中有一个变量x。 如何从变量中找到字符串'x'。

答:如果我正确理解你的问题,你想要从变量的值到它的名字。 这在Python中实际上是不可能的。

在Python中,确实没有任何“变量”这样的东西。 Python真正拥有的是“名称”,它们可以绑定对象。 它对象可能会绑定哪些名称(如果有的话)没有区别。 它可能会绑定几十个不同的名称,或者没有。

考虑这个例子:

foo = 1
bar = foo
baz = foo

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

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

在Python中,名称是访问对象的一种方式,因此无法直接使用名称。 您可以搜索locals()来查找值并恢复名称,但这最多只是一个客厅技巧。 在上面的例子中, foobarbaz中的哪一个是“正确的”答案? 它们都指的是完全相同的对象。

PS以上是我之前写过的一个有点编辑的答案版本 我想这次我的措辞做得更好了。

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

关于__repr__()

由repr()内置函数和字符串转换(反向引号)调用,以计算对象的“官方”字符串表示形式。

请参阅此处的文档: 对象。 repr (个体经营)

史蒂文哈对这个问题有很好的答案。 但是,如果您确实想要在命名空间字典中查找,那么您可以获取特定范围/命名空间中给定值的所有名称,如下所示:

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),则不需要将locals 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'

最后,如果您正在使用类属性并且希望它们知道它们的名称(描述符是明显的用例),那么您可以像使用Django ORM和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'

有三种方法可以在python中获取对象的“字符串”表示形式: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'}"

在这种情况下,所有三个方法都生成相同的输出,区别在于str()调用dict.__str__() ,而repr()调用dict.__repr__() str()用于字符串插值,而repr()在打印列表或字典时由Python内部用于列表或字典中的每个对象。

正如Tendayi Mawushe上面提到的那样,repr生成的字符串不一定是人类可读的。

此外, .__str__()的默认实现是调用.__repr__() ,因此如果类没有自己覆盖.__str__() ,则使用从.__repr__()返回的值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM