2009-11-03 8 views
6

Tengo una variable x en python. ¿Cómo puedo encontrar la cadena 'x' de la variable? Aquí está mi intento:¿Cómo obtengo la representación de cadena de una variable en python?

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

Los resultados son los siguientes:

Global var x = 123 
Local var x = 321 

La receta anterior parece un poco ONU-Pythonesque. ¿Hay una manera mejor/más corta de lograr el mismo resultado?

+2

¿Qué es lo que realmente no? No hay llamadas sin una 'x', por lo que puede usar print 'var x =% s'% x pero no lo hace. ¿Por qué? – tuergeist

+0

duplicado: http://stackoverflow.com/questions/1534504/convert-variable-name-to-string –

+0

también duplicado http://stackoverflow.com/questions/592746/how-can-you-print-a-variable -name-in-python-closed – fortran

Respuesta

13

Q: Tengo una variable x en Python. ¿Cómo puedo encontrar la cadena 'x' de la variable?

A: Si estoy entendiendo su pregunta correctamente, quiere pasar del valor de una variable a su nombre. Esto no es realmente posible en Python.

En Python, realmente no hay tal cosa como una "variable". Lo que realmente tiene Python son los "nombres" que pueden tener objetos vinculados a ellos. No hace ninguna diferencia para el objeto a qué nombres, si hay alguno, podría estar vinculado. Podría estar ligado a docenas de nombres diferentes, o ninguno.

Considere este ejemplo:

foo = 1 
bar = foo 
baz = foo 

Ahora, supongamos que tiene el objeto número entero con valor 1, y que desea trabajar hacia atrás y encontrar su nombre. ¿Qué imprimirías? Tres nombres diferentes tienen ese objeto vinculado a ellos, y todos son igualmente válidos.

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

En Python, un nombre es una manera de acceder a un objeto, así que no hay manera de trabajar con los nombres directamente. Es posible que pueda buscar a través del locals() para encontrar el valor y recuperar un nombre, pero eso es, en el mejor de los casos, un truco de salón. Y en mi ejemplo anterior, ¿cuál de foo, bar y baz es la respuesta "correcta"? Todos ellos se refieren exactamente al mismo objeto.

P.S. Lo anterior es una versión algo editada de an answer I wrote before.. Creo que hice un mejor trabajo al redactar las cosas esta vez.

+0

Sí, eso es posible usando la función locals(). Devuelve un diccionario de todas las variables en el ámbito local (incluidos objetos, métodos y funciones). – elzapp

+0

Gracias por la respuesta. Me dejé llevar por una pista diferente. Tu publicación anterior cambió mi opinión sobre lo que quería hacer. – Johan

7

Creo que la forma general de lo que desea es repr() o el método __repr__() de un objeto.

en lo que respecta a __repr__():

Llamado por el repr() función incorporada y por la conversión de series (inverso comillas) para calcular la representación “oficial” de cadena de un objeto.

Consulte la documentación aquí: object.repr(self)

+0

Sí, esta es mi interpretación de la pregunta de OPs también. Puede usar repr() para la representación de la declaración python del objeto, str() para la representación de cadena ascii y unicode() para la representación de cadena Unicode. – btk

0

Hay tres maneras de conseguir "la" representación de cadena de un objeto en 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: interpolación de cadenas :

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

En este caso, los tres métodos generaron la misma salida, los di La diferencia es que str() llama al dict.__str__(), mientras que repr() llama al dict.__repr__(). str() se usa en la interpolación de cadenas, mientras que Python usa internamente repr() en cada objeto de una lista o dict cuando se imprime la lista o dict.

Como mencionó anteriormente Tendayi Mawushe, la cadena producida por repr no es necesariamente legible por humanos.

3

stevenha tiene una gran respuesta a esta pregunta. Pero, si realmente no quiere hurgar en los diccionarios de espacio de nombres de todos modos, se pueden obtener todos los nombres para un valor dado en un determinado ámbito/espacio de nombres de la siguiente manera:

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

Si está trabajando con un pitón que tiene soporte de marco de pila (la mayoría lo hace, CPython lo hace), no es necesario que pase el dict local en la función names_of; la función puede recuperar ese diccionario del marco de su llamador en sí:

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

Si está trabajando con un tipo de valor que se puede asignar un atributo de nombre a, puede darle un nombre, y luego usar esa:

class SomeClass(object): 
    pass 

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


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

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

por último, si usted está trabajando con los atributos de clase y usted quiere que ellos sepan sus nombres (descriptores son el caso de uso obvio), que puede hacer trucos con la programación metaclase como lo hacen en el ORM de Django y SQLAlchemy definiciones de tabla de estilo declarativo:

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' 
Cuestiones relacionadas