Как получить строковое представление переменной в 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__()
значение, возвращаемое из это.