Как получить строковое представление переменной в python?

у меня есть переменная x в python. Как я могу найти строку '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

вышеуказанный рецепт кажется немного ООН-свойственным только им версиях. Есть ли лучший / более короткий способ достичь того же результата?

4 ответов


Q: у меня есть переменная x в python. Как я могу найти строку 'X' из переменной.

A: если я правильно понимаю ваш вопрос, вы хотите перейти от значения переменной к ее имени. Это действительно невозможно в Python.

в Python действительно нет такой вещи, как "переменная". На самом деле Python имеет "имена", которые могут иметь привязанные к ним объекты. Для объекта не имеет значения, с какими именами он связан, если таковые имеются. Это может быть связаны десятками разных имен, или ни одного.

Рассмотрим пример:

foo = 1
bar = foo
baz = foo

теперь предположим, что у вас есть целочисленный объект со значением 1, и вы хотите работать в обратном направлении и найти его имя. Что бы вы напечатали? Три разных имени имеют этот объект, связанный с ними, и все они одинаково действительны.

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

в Python имя-это способ доступа к объекту, поэтому нет способа работать с именами напрямую. Вы могли бы искать через locals() найти значение и восстановить имя, но это на лучший трюк. И в моем примере выше, который из foo, bar и baz - это "правильный" ответ? Все они относятся к одному и тому же объекту.

П. С. выше-это несколько отредактированная версия ответ, который я написал раньше. я думаю, что на этот раз я лучше справился с формулировками.


Я считаю, что общая форма того, что вы хотите, это repr() или __repr__() метод объекта.

в отношении __repr__():

вызывается встроенной функцией repr() и строковыми преобразованиями (реверс котировки), чтобы вычислить " официальный" строковое представление объекта.

см. документы здесь:


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 делает), не требуется, чтобы вы передавали местных жителей в 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']

если вы работаете с типом значения, которые можно присвоить атрибут name, вы можете дать ему имя, а затем использовать:

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 внутренне для каждого объекта в списке или dict при печати списка или словарь.

как упоминал выше Тендайи Мавуше, строка, производимая repr, не обязательно читается человеком.

кроме того, реализация по умолчанию .__str__() позвонить .__repr__(), поэтому, если класс не имеет собственных переопределений на .__str__() значение, возвращаемое из это.