3

I want to define a class with it's __repr__ method defined in such a way that it will write out only the names and values of all attributes that are not methods. How can I do this? I have managed to write it like this, but I realize that this does not check for the attribute type.

class Example:
    def __repr__(self):
        return "\n".join(["%s: %s" % (x, getattr(self, x)) for x in dir(self) if not x.startswith('__')])

What is missing here is the check for the type of the attribute.

Amar
  • 63
  • 1
  • 8

3 Answers3

5

You can use inspect for something like this:

from inspect import ismethod,getmembers

class Example:
    def __repr__(self):
        return "\n".join("%s: %s" % (k, v) for (k,v) in getmembers(self,lambda x: not ismethod(x)))

    def method(self):
        return 1

a = Example()
a.foo = 'bar'
print a

This also picks up the double underscore attributes (__module__, __doc__). If you don't want those, you can pretty easily filter them out.

mgilson
  • 300,191
  • 65
  • 633
  • 696
  • It will pick up `@property` and class variables as well. – kennytm Apr 29 '13 at 17:49
  • I would argue that it *should* pick up both of those cases. Definitely property objects. After all, from an API perspective, there's no difference between a property and an attribute ... but I suppose that really depends on what OP wants :). – mgilson Apr 29 '13 at 17:51
2

Try built-in function callable: http://docs.python.org/2/library/functions.html#callable

ndpu
  • 22,225
  • 6
  • 54
  • 69
  • 2
    The downside of this is that you can make a callable object an attribute: `e = Example(); e.foo = lambda x:x*x` for example. – mgilson Apr 29 '13 at 17:36
  • Better is [this answer](http://stackoverflow.com/a/1260997/1322401) to [Assert that variable is instance method?](http://stackoverflow.com/questions/1259963/python-assert-that-variable-is-instance-method). – Steven Rumbalski Apr 29 '13 at 17:37
2

Assuming your class does not define __slots__, you could also just iterate the instance's __dict__ (or via the vars() function).

class Superclass:
    def __init__(self, w):
        self.w = w

class Example(Superclass):
    def __init__(self, x, y, z):
        super().__init__(1234)
        self.x = x
        self.y = y
        self.z = z

    @property
    def x_prop(self):
        return self.x

    @classmethod
    def do_something(cls, z):
        return str(cls) + str(z)

    def __call__(self):
        return 4444

    class_property = 42


    def __repr__(self):
        return "\n".join("%s: [%s]" % (k, v) for (k,v) in vars(self).items())

example = Example(2, lambda y: z, '4')
example2 = Example(example, 6j, b'90')

print(repr(example2))

This prints

x: [x: [2]
y: [<function <lambda> at 0x7f9368b21ef0>]
z: [4]
w: [1234]]
y: [6j]
z: [b'90']
w: [1234]
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005