¿Cómo obtener variables de instancia en Python?
-
01-07-2019 - |
Pregunta
¿Existe un método integrado en Python para obtener una matriz de todas las variables de instancia de una clase?Por ejemplo, si tengo este código:
class hi:
def __init__(self):
self.ii = "foo"
self.kk = "bar"
¿Hay alguna manera de hacer esto?
>>> mystery_method(hi)
["ii", "kk"]
Editar:Originalmente había solicitado variables de clase por error.
Solución
Cada objeto tiene un __dict__
variable que contiene todas las variables y sus valores.
Prueba esto
>>> hi_obj = hi()
>>> hi_obj.__dict__.keys()
Otros consejos
Utilice vars()
class Foo(object):
def __init__(self):
self.a = 1
self.b = 2
vars(Foo()) #==> {'a': 1, 'b': 2}
vars(Foo()).keys() #==> ['a', 'b']
Normalmente no se pueden obtener atributos de instancia dada solo una clase, al menos no sin crear una instancia de la clase.Sin embargo, puede obtener atributos de instancia dada una instancia o atributos de clase dada una clase.Consulte el módulo 'inspeccionar'.No puede obtener una lista de atributos de instancia porque las instancias realmente pueden tener cualquier cosa como atributo y, como en su ejemplo, la forma normal de crearlas es simplemente asignarlas en el método __init__.
Una excepción es si su clase usa ranuras, que es una lista fija de atributos que la clase permite que tengan las instancias.Las tragamonedas se explican en http://www.python.org/2.2.3/descrintro.html, pero existen varios inconvenientes con las tragamonedas;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.
Tanto el método Vars() como el dict funcionarán para el ejemplo que publicó el OP, pero no funcionarán para objetos definidos "vagamente" como:
class foo:
a = 'foo'
b = 'bar'
Para imprimir todos los atributos no invocables, 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
También puedes probar si un objeto tiene una variable específica con:
>>> hi_obj = hi()
>>> hasattr(hi_obj, "some attribute")
Sugerir
>>> print vars.__doc__
vars([object]) -> dictionary
Without arguments, equivalent to locals().
With an argument, equivalent to object.__dict__.
En otras palabras, básicamente simplemente envuelve __dict__
Su ejemplo muestra "variables de instancia", no realmente variables de clase.
Pase a ver hi_obj.__class__.__dict__.items()
para las variables de clase, junto con otros miembros de la clase, como funciones 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.
Aunque no es una respuesta directa a la pregunta de OP, existe una manera bastante sencilla 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 contiene todo tipo de cosas interesantes.Te permite hacer algunas cosas interesantes.Aquí hay un ejemplo de cómo lo he usado:
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'