How to get instance variables in Python?

Is there a built-in method in Python to get an array of all a class’ instance variables? For example, if I have this code:

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

Is there a way for me to do this:

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

Edit: I originally had asked for class variables erroneously.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Every object has a __dict__ variable containing all the variables and its values in it.

Try this

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

Method 2

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

Method 3

You normally can’t get instance attributes given just a class, at least not without instantiating the class. You can get instance attributes given an instance, though, or class attributes given a class. See the ‘inspect’ module. You can’t get a list of instance attributes because instances really can have anything as attribute, and — as in your example — the normal way to create them is to just assign to them in the __init__ method.

An exception is if your class uses slots, which is a fixed list of attributes that the class allows instances to have. Slots are explained in http://www.python.org/2.2.3/descrintro.html, but there are various pitfalls with slots; they affect memory layout, so multiple inheritance may be problematic, and inheritance in general has to take slots into account, too.

Method 4

Both the Vars() and dict methods will work for the example the OP posted, but they won’t work for “loosely” defined objects like:

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

To print all non-callable attributes, you can use the following function:

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.%snn') % i

Method 5

You can also test if an object has a specific variable with:

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

Method 6

Your example shows “instance variables”, not really class variables.

Look in hi_obj.__class__.__dict__.items() for the class variables, along with other other class members like member functions and the containing module.

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

Class variables are shared by all instances of the class.

Method 7

Suggest

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

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

In otherwords, it essentially just wraps __dict__

Method 8

Although not directly an answer to the OP question, there is a pretty sweet way of finding out what variables are in scope in a function. take a look at this 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')
>>>

The func_code attribute has all kinds of interesting things in it. It allows you todo some cool stuff. Here is an example of how I have have used this:

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'

Method 9

built on dmark’s answer to get the following, which is useful if you want the equiv of sprintf and hopefully will help someone…

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

Method 10

Sometimes you want to filter the list based on public/private vars. E.g.

def pub_vars(self):
    """Gives the variable names of our instance we want to expose
    """
    return [k for k in vars(self) if not k.startswith('_')]

Method 11

You will need to first, examine the class, next, examine the bytecode for functions, then, copy the bytecode, and finally, use the __code__.co_varnames. This is tricky because some classes create their methods using constructors like those in the types module. I will provide code for it on GitHub.

Method 12

Based on answer of Ethan Joffe

def print_inspect(obj):
  print(f"{type(obj)}n")
  var_names = [attr for attr in dir(obj) if not callable(getattr(obj, attr)) and not attr.startswith("__")]
  for v in var_names: 
    print(f"tself.{v} = {getattr(obj, v)}n")


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x