Dealing with the __str__ method in classes with lots of attributes

Cameron Simpson cs at zip.com.au
Thu May 10 20:15:35 EDT 2012


On 10May2012 15:33, Andreas Tawn <andreas.tawn at ubisoft.com> wrote:
| Say I've got a class...
| 
| class test(object):
|     def __init__(self):
|         self.foo = 1
|         self.bar = 2
|         self.baz = 3
| 
| I can say...
| 
| def __str__(self):
|    return "foo: {0}\nbar: {1}\nbaz: {2}".format(self.foo, self.bar, self.baz)
| 
| and everything's simple and clean and I can vary the formatting if I need to.
| 
| This gets ugly when the class has a lot of attributes because the string construction gets very long.

This issue bit me once too often a few months ago, and now I have a
class called "O" from which I often subclass instead of from "object".
Its main purpose is a friendly __str__ method, though it also has a
friendly __init__.

Code:

    class O(object):
      ''' A bare object subclass to allow storing arbitrary attributes.
          It also has a nicer default str() action, and an aggressive repr().
      '''

      def __init__(self, **kw):
        ''' Initialise this O.
            Fill in attributes from any keyword arguments if supplied.
            This call can be omitted in subclasses if desired.
        '''
        for k in kw:
          setattr(self, k, kw[k])

      def __str__(self):
        return ( "<%s %s>"
                 % ( self.__class__.__name__,
                     ",".join([ "%s=%s" % (attr, getattr(self, attr))
                                for attr in sorted(dir(self)) if attr[0].isalpha()
                              ])
                   )
               )

So I have some code thus:

  from cs.misc import O
  ......
  class FilterModes(O):
    def __init__(self, **kw):
        # special case one parameter
        self._maildb_path = kw.pop('maildb_path')
        self._maildb_lock = allocate_lock()
        O.__init__(self, **kw)
  ......
  filter_modes = FilterModes(justone=justone,
                             delay=delay,
                             no_remove=no_remove,
                             no_save=no_save,
                             maildb_path=os.environ['MAILDB'],
                             maildir_cache={})


This removes a lot of guff from some common procedures.

Hope this helps,
-- 
Cameron Simpson <cs at zip.com.au> DoD#743
http://www.cskk.ezoshosting.com/cs/

There's a fine line between pathos and pathetic.
        - David Stivers stiv at stat.rice.edu DoD #857



More information about the Python-list mailing list