Jak uzyskać zmienne instancji w Pythonie?

Czy istnieje wbudowana metoda w Pythonie, aby uzyskać tablicę wszystkich zmiennych instancji klasy? Na przykład, jeśli mam ten kod:

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

Czy jest dla mnie sposób, aby to zrobić:

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

Edit: początkowo błędnie prosiłem o zmienne klasy.

Author: ROMANIA_engineer, 2008-09-20

8 answers

Każdy obiekt posiada zmienną __dict__ zawierającą wszystkie zmienne i ich wartości.

Spróbuj tego

>>> hi_obj = hi()
>>> hi_obj.__dict__.keys()
 104
Author: cnu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-20 19:34:17

Użyj vars ()

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

vars(Foo()) #==> {'a': 1, 'b': 2}
vars(Foo()).keys() #==> ['a', 'b']
 82
Author: Jeremy Cantrell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-06 03:54:15

Normalnie nie można uzyskać atrybutów instancji podanych tylko klasie, przynajmniej nie bez utworzenia instancji klasy. Można jednak uzyskać atrybuty instancji, które podano instancji, lub atrybuty klasy, które podano klasie. Patrz moduł "inspect". Nie możesz uzyskać listy atrybutów instancji, ponieważ instancje naprawdę mogą mieć cokolwiek jako atrybut, a-jak w twoim przykładzie-normalnym sposobem ich tworzenia jest po prostu przypisanie do nich w metodzie _ _ init__.

Wyjątkiem jest, jeśli twoja klasa używa slotów, która jest stałą listą atrybutów, które Klasa pozwala instancjom mieć. Sloty są wyjaśnione w http://www.python.org/2.2.3/descrintro.html , ale istnieją różne pułapki związane z slotami; wpływają one na układ pamięci, więc wielokrotne dziedziczenie może być problematyczne, a dziedziczenie w ogóle musi uwzględniać również sloty.

 13
Author: Thomas Wouters,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-20 19:38:01

Zarówno metody Vars() jak i dict będą działać dla przykładu, który opublikował OP, ale nie będą działać dla "luźno" zdefiniowanych obiektów, takich jak:

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

Aby wydrukować wszystkie atrybuty, których nie można wywołać, możesz użyć następującej funkcji:

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
 13
Author: dmark,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-23 21:50:34

Możesz również sprawdzić, czy obiekt ma określoną zmienną z:

>>> hi_obj = hi()
>>> hasattr(hi_obj, "some attribute")
 10
Author: daniel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-20 19:39:31

Zasugeruj

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

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

W otherwords, to w zasadzie tylko zawija _ _ dict _ _

 6
Author: daniel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-20 12:27:43

Twój przykład pokazuje "zmienne instancji", a nie zmienne klas.

Poszukaj w hi_obj.__class__.__dict__.items() zmiennych klasy, wraz z innymi innymi członkami klasy, takimi jak funkcje member i moduł zawierający.

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

Zmienne klasy są współdzielone przez wszystkie instancje klasy.

 5
Author: S.Lott,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-20 19:42:43

Chociaż nie jest to odpowiedź bezpośrednio na pytanie OP, istnieje całkiem słodki sposób na sprawdzenie, jakie zmienne są w zakresie funkcji. spójrz na ten kod:

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

Atrybut func_code zawiera wiele interesujących rzeczy. Pozwala Ci zrobić kilka fajnych rzeczy. Oto przykład, jak to wykorzystałem:

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
Author: tim.tadh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-21 19:46:01