Welcome, guest | Sign In | My Account | Store | Cart

Formats a string using the same notation as a dict-expansion, but using an object as the source for the expansion instead. Attributes from the object are used as source to the expansions.

Python, 24 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import re

exp_rx = re.compile('%\((\w+)\)')

def format_obj(obj, text):
    """
    >>> o = Duck(one='one', two='two', three=5)
    >>> format_obj(o, '%(one)s %(two)s %(three)d')
    'one two 5'
    """
    return text % dict((a, getattr(obj, a))
                               for a in re.findall(exp_rx, text))

# ---- Support for the doctest from here down:

class Duck(object):
    """Quack!"""

    def __init__(self, **kw):
        self.__dict__.update(kw)

if __name__ == '__main__':
    import doctest
    doctest.testmod()

3 comments

Chris Jones 12 years, 3 months ago  # | flag

I like over-riding the __repr__ method myself:

class Duck(object):

    '''
    >>> Duck(foo=1, bar='2', baz=None)
    <Duck object at 0x28b3a4ec: bar='2', foo=1, baz=None>
    >>> Duck()
    <Duck object at 0x28b36d6c>
    '''

    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)

    def __repr__(self):
        a = ', '.join('%s=%r' % i for i in self.__dict__.items())
        return '<%s object at 0x%x%s%s>' % (
                type(self).__name__, id(self), ': ' if a else '', a)

You can get fancier with it, e.g. skipping private attributes, but I mostly use it for development/debugging and remove it later.

Manfred Moitzi 12 years, 3 months ago  # | flag

Hello!

You got the same result with:

return text % obj.__dict__

What is the advantage of your recipe?

Gabriel Genellina 12 years, 3 months ago  # | flag

Or even simpler:

return text % vars(obj)