2008-09-20 13 views
78

¿Existe un método incorporado en Python para obtener una matriz de todas las variables de instancia de una clase? Por ejemplo, si tengo este código:¿Cómo obtener variables de instancia en Python?

class hi: 
    def __init__(self): 
    self.ii = "foo" 
    self.kk = "bar" 

¿Hay alguna manera para que haga esto:

>>> mystery_method(hi) 
["ii", "kk"] 

Edit: originalmente había pedido variables de clase erróneamente.

+0

Su ejemplo muestra "variables de instancia". Las variables de clase son otra cosa. –

Respuesta

93

Cada objeto tiene una variable __dict__ que contiene todas las variables y sus valores.

probar este ejemplo

>>> hi_obj = hi() 
>>> hi_obj.__dict__.keys() 
+7

FWIW, el módulo de inspección le proporciona un método más confiable que confiar en __dict__, que no todas las instancias tienen. –

+1

¿Qué tipo de instancia no tiene __dict__? Nunca he encontrado uno. –

+3

Ciertos tipos incorporados, como int. Intenta decir "x = 5" y luego "x .__ dict__" y obtendrás un AttributeError –

13

Normalmente, usted no puede obtener atributos dados sólo una clase, al menos no sin una instancia de la clase. Sin embargo, puede obtener atributos de instancia dada una instancia o atributos de clase dada una clase. Vea el módulo 'inspeccionar'. No se puede obtener una lista de atributos de instancia porque las instancias realmente pueden tener algo como atributo y, como en su ejemplo, la manera normal de crearlos es asignarles el método __init__.

Una excepción es si su clase utiliza ranuras, que es una lista fija de los atributos que la clase permite que las instancias tengan. Las máquinas tragamonedas se explican en http://www.python.org/2.2.3/descrintro.html, pero hay varias dificultades con las ranuras; afectan el diseño de la memoria, por lo que la herencia múltiple puede ser problemática, y la herencia en general también debe tener en cuenta las ranuras.

+0

Downvoting porque "no se puede obtener una lista de atributos de instancia" es simplemente incorrecto: tanto vars() como __dict__ le dan exactamente eso. –

+2

Supongo que quiso decir "no se puede obtener una lista de todos los posibles atributos de instancia". Por ejemplo, a menudo uso la generación diferida y el decorador @property para agregar una variable de instancia la primera vez que se solicita. El uso de __dict__ le informará sobre esta variable una vez que existió, pero no de antemano. –

+4

No he votado negativamente y, por favor, tenga en cuenta lo que dije en realidad: no se puede obtener una lista de atributos de instancia * dada solo por una clase *, que es lo que el código que acompaña la pregunta intenta hacer. –

9

También puede comprobar si un objeto tiene una variable específica con:

>>> hi_obj = hi() 
>>> hasattr(hi_obj, "some attribute") 
4

Su ejemplo muestra "variables de instancia", no variables de clase realmente.

Mire en hi_obj.__class__.__dict__.items() para las variables de clase, junto con otros miembros de clase como funciones de miembro y el módulo contenedor.

class Hi(object): 
    class_var = (23, 'skidoo') # class variable 
    def __init__(self): 
     self.ii = "foo" # instance variable 
     self.jj = "bar" 

Las variables de clase son compartidas por todas las instancias de la clase.

73

Use vars()

class Foo(object): 
    def __init__(self): 
     self.a = 1 
     self.b = 2 

vars(Foo()) #==> {'a': 1, 'b': 2} 
vars(Foo()).keys() #==> ['a', 'b'] 
+6

+1 Personalmente creo que esta sintaxis es más limpia que con __dict__, ya que se supone que los atributos con doble guión bajo son "privados" en la sintaxis de Python. –

+2

@Martin: '__method' es privado,' __method__' es un método especial, no necesariamente privado; Me gustaría decir que los métodos especiales definen las capacidades de un objeto en lugar de los métodos. – u0b34a0f6ae

+2

'__method__' es bastante feo, y creo que han sido nombrados de esa manera para tratar de disuadir a las personas de usarlos a menos que sea absolutamente necesario. En este caso tenemos la alternativa vars(). –

6

sugieren

>>> print vars.__doc__ 
vars([object]) -> dictionary 

Without arguments, equivalent to locals(). 
With an argument, equivalent to object.__dict__. 

En otras palabras, que esencialmente sólo envuelve __dict__

5

Aunque no directamente una respuesta a la pregunta OP, hay una muy dulce forma de descubrir qué variables están dentro del alcance de una función. Echa un vistazo a este código:

>>> def f(x, y): 
    z = x**2 + y**2 
    sqrt_z = z**.5 
    return sqrt_z 

>>> f.func_code.co_varnames 
('x', 'y', 'z', 'sqrt_z') 
>>> 

El atributo func_code tiene todo tipo de cosas interesantes en él. Te permite hacer cosas geniales.Aquí está un ejemplo de cómo he utilizado este:

def exec_command(self, cmd, msg, sig): 

    def message(msg): 
     a = self.link.process(self.link.recieved_message(msg)) 
     self.exec_command(*a) 

    def error(msg): 
     self.printer.printInfo(msg) 

    def set_usrlist(msg): 
     self.client.connected_users = msg 

    def chatmessage(msg): 
     self.printer.printInfo(msg) 

    if not locals().has_key(cmd): return 
    cmd = locals()[cmd] 

    try: 
     if 'sig' in cmd.func_code.co_varnames and \ 
         'msg' in cmd.func_code.co_varnames: 
      cmd(msg, sig) 
     elif 'msg' in cmd.func_code.co_varnames: 
      cmd(msg) 
     else: 
      cmd() 
    except Exception, e: 
     print '\n-----------ERROR-----------' 
     print 'error: ', e 
     print 'Error proccessing: ', cmd.__name__ 
     print 'Message: ', msg 
     print 'Sig: ', sig 
     print '-----------ERROR-----------\n' 
11

Tanto el Vars() y métodos dict trabajará para el ejemplo de la OP publicado, pero no van a trabajar para los objetos "en términos generales" se definen como:

class foo: 
    a = 'foo' 
    b = 'bar' 

Para imprimir todos los atributos que no son exigibles, se puede utilizar la siguiente función:

def printVars(object): 
    for i in [v for v in dir(object) if not callable(getattr(object,v))]: 
     print '\n%s:' % i 
     exec('print object.%s\n\n') % i 
+4

'exec ('print object.% S \ n \ n')% i' debe escribirse como' print getattr (object, i) ' – user102008

Cuestiones relacionadas