8

If I have the following class, what's the best way of getting the exact list of variables and methods, excluding those from the superclass?

class Foo(Bar):
  var1 = 3.14159265
  var2 = Baz()
  @property
  def var3(self):
      return 42
  def meth1(self, var):
      return var

I want the tuple ('var1','var2','var3','meth1') with minimum overhead. This is being run in a Django environment, which seems to be putting some of it's class instance variables in the read-only __dict__ variable; a feat which I can't find a way to replicate.

Here's what I'm seeing while playing with it, any suggestions beyond trimming out the __* from the dir() or manually listing them?

>>> a=Foo()
>>> a
<__main__.Foo instance at 0x7f48c1e835f0>
>>> dict(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: iteration over non-sequence
>>> dir(a)
['__doc__', '__module__', 'meth1', 'var1', 'var2', 'var3']
>>> a.__dict__
{}
BVMiko
  • 97
  • 1
  • 1
  • 9

5 Answers5

10

If the class and its superclasses are known, something like:

tuple(set(dir(Foo)) - set(dir(Bar)))

If you want it to be more generic, you can get a list of the base classes using something like

bases = Foo.mro()

...and then use that list to subtract out attributes from all the base classes.

bgporter
  • 35,114
  • 8
  • 59
  • 65
  • I'm going to use your technique in my project, as the base class is predictable. I'll also implement some caching routine and save it as a method variable, thanks for the set manipulation tip! – BVMiko Apr 10 '11 at 05:46
  • 1
    keep in mind that mro() only works for new-style classes ie. those subclassing from 'object' – Petri Jan 07 '15 at 10:47
6

In your example, a is an instance, its __dict__ will include all variables set in its __init__ function. To get all class variables, use a.__class__.__dict__

highBandWidth
  • 16,751
  • 20
  • 84
  • 131
3

A third answer is the inspect module which does the same as above

Mike Ramirez
  • 10,750
  • 3
  • 26
  • 20
1
def getVariablesClass(inst):
var = []
cls = inst.__class__
for v in cls.__dict__:
    if not callable(getattr(cls, v)):
        var.append(v)

return var

if you want exclude inline variables check names on the __ at the start and the end of variable

binx
  • 11
  • 1
1

If you want to introspect your own classes, you can do it on class definition and cache it by the way:

class Bar:
    parent_prop = 0


class Foo(Bar):
    my_prop1 = 1
    my_prop2 = 2

    def method1(self):
        pass

    SYMBOLS = [k for k in locals().keys() if not k.startswith('_')]



if __name__ == '__main__':
    print(Foo.SYMBOLS)

Output:

['my_prop1', 'my_prop2', 'method1']
mnesarco
  • 2,619
  • 23
  • 31