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

发布于 2024-08-09 14:01:39 字数 411 浏览 2 评论 0原文

我在 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风格。有没有更好/更短的方法来达到相同的结果?

I have a variable x in python. How can i find the string 'x' from the variable. Here is my attempt:

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()

The results are:

Global var x = 123
Local var x = 321

The above recipe seems a bit un-pythonesque. Is there a better/shorter way to achieve the same result?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梦在深巷 2024-08-16 14:01:39

问:我在 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 以上是我之前写的答案的稍微编辑版本。 我认为这次我在措辞方面做得更好。

Q: I have a variable x in python. How can i find the string 'x' from the variable.

A: If I am understanding your question properly, you want to go from the value of a variable to its name. This is not really possible in Python.

In Python, there really isn't any such thing as a "variable". What Python really has are "names" which can have objects bound to them. It makes no difference to the object what names, if any, it might be bound to. It might be bound to dozens of different names, or none.

Consider this example:

foo = 1
bar = foo
baz = foo

Now, suppose you have the integer object with value 1, and you want to work backwards and find its name. What would you print? Three different names have that object bound to them, and all are equally valid.

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

In Python, a name is a way to access an object, so there is no way to work with names directly. You might be able to search through locals() to find the value and recover a name, but that is at best a parlor trick. And in my above example, which of foo, bar, and baz is the "correct" answer? They all refer to exactly the same object.

P.S. The above is a somewhat edited version of an answer I wrote before. I think I did a better job of wording things this time.

酒浓于脸红 2024-08-16 14:01:39

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

关于 __repr__() :

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

请参阅此处的文档:object.repr(self)< /a>

I believe the general form of what you want is repr() or the __repr__() method of an object.

with regards to __repr__():

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

See the docs here: object.repr(self)

暮年慕年 2024-08-16 14:01:39

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

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 也是如此),不需要将本地字典传递到 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'

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:

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']

If you're working with a Python that has stack frame support (most do, CPython does), it isn't required that you pass the locals dict into the names_of function; the function can retrieve that dictionary from its caller's frame itself:

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']

If you're working with a value type that you can assign a name attribute to, you can give it a name, and then use that:

class SomeClass(object):
    pass

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


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

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

Finally, if you're working with class attributes and you want them to know their names (descriptors are the obvious use case), you can do cool tricks with metaclass programming like they do in the Django ORM and SQLAlchemy declarative-style table definitions:

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'
梦里梦着梦中梦 2024-08-16 14:01:39

在 python 中,有三种方法可以获取对象的“the”字符串表示形式:
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__()返回的值。

There are three ways to get "the" string representation of an object in 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: string interpolation:

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

In this case all three methods generated the same output, the difference is that str() calls dict.__str__(), while repr() calls dict.__repr__(). str() is used on string interpolation, while repr() is used by Python internally on each object in a list or dict when you print the list or dict.

As Tendayi Mawushe mentiones above, string produced by repr isn't necessarily human-readable.

Also, the default implementation of .__str__() is to call .__repr__(), so if the class does not have it's own overrides to .__str__(), the value returned from .__repr__() is used.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文