web-dev-qa-db-fra.com

Comment obtenir des variables d'instance en Python?

Existe-t-il une méthode intégrée dans Python pour obtenir un tableau de toutes les variables d'instance d'une classe? Par exemple, si j'ai ce code:

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

Y a-t-il un moyen pour moi de faire ceci:

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

Edit: Au départ, j'avais demandé des variables de classe par erreur.

104
Chris Bunch

Chaque objet a un __dict__ variable contenant toutes les variables et leurs valeurs.

Essaye ça

>>> hi_obj = hi()
>>> hi_obj.__dict__.keys()
125
cnu

Utilisez vars ()

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

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

Vous ne pouvez normalement pas obtenir d'attributs d'instance uniquement avec une classe, du moins pas sans instancier la classe. Vous pouvez cependant obtenir des attributs d'instance pour une instance ou des attributs de classe pour une classe. Voir le module 'inspecter'. Vous ne pouvez pas obtenir une liste d'attributs d'instance, car les instances peuvent vraiment avoir n'importe quoi comme attribut et, comme dans votre exemple, la manière habituelle de les créer consiste simplement à leur assigner la méthode __init__.

Une exception est si votre classe utilise des slots, qui est une liste fixe d'attributs que la classe autorise aux instances. Les slots sont expliqués dans http://www.python.org/2.2.3/descrintro.html , mais il existe divers pièges avec les slots; ils affectent la structure de la mémoire, de sorte que l'héritage multiple peut être problématique, et l'héritage en général doit également prendre en compte les slots.

14
Thomas Wouters

Les méthodes Vars () et dict fonctionneront pour l'exemple affiché par le PO, mais ne fonctionneront pas pour des objets définis "de manière lâche" tels que:

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

Pour imprimer tous les attributs non appelables, vous pouvez utiliser la fonction suivante:

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
14
dmark

Vous pouvez également tester si un objet a une variable spécifique avec:

>>> hi_obj = hi()
>>> hasattr(hi_obj, "some attribute")
10
daniel

Suggérer

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

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

En d'autres termes, cela enveloppe essentiellement __dict__

6
daniel

Bien qu'il ne s'agisse pas directement d'une réponse à la question OP, il existe un moyen très simple de déterminer quelles variables sont dans la portée d'une fonction. jetez un oeil à ce code:

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

L'attribut func_code contient toutes sortes de choses intéressantes. Cela vous permet de faire des trucs sympas. Voici un exemple de la façon dont j'ai utilisé ceci:

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'
5
tim.tadh

Votre exemple montre "variables d'instance", pas vraiment des variables de classe.

Recherchez dans hi_obj.__class__.__dict__.items() les variables de classe, ainsi que d'autres membres de la classe tels que les fonctions membres et le module qui les contient.

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

Les variables de classe sont partagées par toutes les instances de la classe.

5
S.Lott

construit sur la réponse de dmark pour obtenir ce qui suit, ce qui est utile si vous voulez l'équivalent de sprintf et si tout va bien aider quelqu'un ...

def sprint(object):
    result = ''
    for i in [v for v in dir(object) if not callable(getattr(object, v)) and v[0] != '_']:
        result += '\n%s:' % i + str(getattr(object, i, ''))
    return result
0
Ethan Joffe