Print all properties of a Python Class [duplicate]
Asked Answered
A

6

262

I have a class Animal with several properties like:


class Animal(object):
    def __init__(self):
        self.legs = 2
        self.name = 'Dog'
        self.color= 'Spotted'
        self.smell= 'Alot'
        self.age  = 10
        self.kids = 0
        #many more...

I now want to print all these properties to a text file. The ugly way I'm doing it now is like:


animal=Animal()
output = 'legs:%d, name:%s, color:%s, smell:%s, age:%d, kids:%d' % (animal.legs, animal.name, animal.color, animal.smell, animal.age, animal.kids,)

Is there a better Pythonic way to do this?

Archambault answered 11/5, 2011 at 19:51 Comment(5)
Did you try searching for questions related to locating all properties of a class? It's been asked. #1215908 for example.Outbid
@S.Lott: Although the OP asked specifically about properties of a class, from their example code I think it's fairly obvious they're not taking about data descriptors.Moving
Relevant: #1398522Jerold
Python offers the vars() function which returns a 'dictionary' of all the instance attributes along with their values. It is similar to the above methods, the only difference being, vars() focuses only on instance attributes and also returns their values along with them.Moorefield
these are attributes of an instance, not a classBotulin
C
469

In this simple case you can use vars():

an = Animal()
attrs = vars(an)
# {'kids': 0, 'name': 'Dog', 'color': 'Spotted', 'age': 10, 'legs': 2, 'smell': 'Alot'}
# now dump this in some way or another
print(', '.join("%s: %s" % item for item in attrs.items()))

If you want to store Python objects on the disk you should look at shelve — Python object persistence.

Churchyard answered 11/5, 2011 at 20:1 Comment(7)
Oh nice, never used vars like that! I thought it just acted like locals(), didn't know you could use it on a class/module. Very useful!Havildar
vars only works if you are using __dict__ to store the attributes (which is the default behaviour for Python objects). Refer to @BasicWolf's answer if you are using __slots__Preterit
Note that in this way you get unordered results. If you need to print for example in order of declaration, and you do not want to do it manually, check thisCigarillo
How would you use this to print something like: an.name = Dog? I tried the following, does not work. '''f.write('\n'.join(["{}.{} = '{}'".format(myname.name, (k for k in myname.__dict__.keys()),(v for v in myname.__dict__.values()))]))'''Hent
TypeError: vars() argument must have __dict__ attributeKarnes
Thanks but the name "BasicWolf" disappeared ... 😅 (possibly because of a renaming).Vespucci
The second answer was written by someone with a wolf as an avatar. See https://mcmap.net/q/109042/-print-all-properties-of-a-python-class-duplicateLiberality
C
122

Another way is to call the dir() function (see https://docs.python.org/2/library/functions.html#dir).

a = Animal()
dir(a)   
>>>
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__',
 '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', 
 '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 
 '__weakref__', 'age', 'color', 'kids', 'legs', 'name', 'smell']

Note, that dir() tries to reach any attribute that is possible to reach.

Then you can access the attributes e.g. by filtering with double underscores:

attributes = [attr for attr in dir(a) 
              if not attr.startswith('__')]

This is just an example of what is possible to do with dir(), please check the other answers for proper way of doing this.

Cullin answered 11/5, 2011 at 20:10 Comment(7)
This is probably the right approach, but it should be pointed out that what it's doing is printing out the attributes, not the things called Properties in new-style classes in Python, and that it's doing it based on an instance of a class, not the class itself (because these attributes don't exist until the class instance is created and __init__() is called). Also if any other attributes are created later, they will be omitted, obviously.Moving
Indeed. But I bet, it's really hard to teach one the overwhelming power of Python's dynamic constructions (objects, types, meta-classes, classes) unless one face them.Cullin
A better filtering (by user235925 on #1398522) [attr for attr in dir(a) if not callable(getattr(Animal,attr)) and not attr.startswith("__")]Concettaconcettina
Works with @property as wellLegist
The only thing that works with PyUNO LibreOffice API.Susysuter
filter(lambda x: not x.startswith('__'), dir(object)) - for list only filter(lambda x: not x.startswith('__'), object.__dict__) - for dict. For class attributes you will want to access object.__class__ and then dir it or __dict__Reg
This is an fast and easy way to inspect any object, since an unfamiliar object may seem like a "dark box", you "unveil" its methods and attributes.Bullish
S
77

Maybe you are looking for something like this?

    >>> class MyTest:
        def __init__ (self):
            self.value = 3
    >>> myobj = MyTest()
    >>> myobj.__dict__
    {'value': 3}
Sophisticated answered 11/5, 2011 at 20:9 Comment(1)
Note since this gives you a dictionary, you can also just look at the keys if you want a quick API reference print(o.__dict__.keys()).Nez
P
11

try ppretty:

from ppretty import ppretty


class Animal(object):
    def __init__(self):
        self.legs = 2
        self.name = 'Dog'
        self.color= 'Spotted'
        self.smell= 'Alot'
        self.age  = 10
        self.kids = 0


print ppretty(Animal(), seq_length=10)

Output:

__main__.Animal(age = 10, color = 'Spotted', kids = 0, legs = 2, name = 'Dog', smell = 'Alot')
Presentable answered 28/7, 2016 at 7:2 Comment(0)
H
6

Here is full code. The result is exactly what you want.

class Animal(object):
    def __init__(self):
        self.legs = 2
        self.name = 'Dog'
        self.color= 'Spotted'
        self.smell= 'Alot'
        self.age  = 10
        self.kids = 0

if __name__ == '__main__':
    animal = Animal()
    temp = vars(animal)
    for item in temp:
        print item , ' : ' , temp[item]
        #print item , ' : ', temp[item] ,
Headward answered 14/3, 2017 at 0:31 Comment(0)
L
4

Just try beeprint

it prints something like this:

instance(Animal):
    legs: 2,
    name: 'Dog',
    color: 'Spotted',
    smell: 'Alot',
    age: 10,
    kids: 0,

I think is exactly what you need.

Lanyard answered 16/9, 2016 at 15:36 Comment(3)
If you're a SQLAlchemy user, this doesn't show your object's content properly.Erosive
@paulochf... please explain... just double checked...we're talking about python here and not SQL....Dioxide
If the referred Python class is a SqlAlchemy model, one could want to print all of its attributes.Erosive

© 2022 - 2024 — McMap. All rights reserved.