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.
This question is related to
python
methods
instance-variables
Every object has a __dict__
variable containing all the variables and its values in it.
Try this
>>> hi_obj = hi()
>>> hi_obj.__dict__.keys()
You can also test if an object has a specific variable with:
>>> hi_obj = hi()
>>> hasattr(hi_obj, "some attribute")
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__
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']
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('_')]
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'
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.
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.%s\n\n') % i
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.
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.
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
Source: Stackoverflow.com