0

I have an object that's constructor accepts *kwargs and sets them as atributes.

class Observable(object):
    def __init__(self, **kwargs):
        for key in kwargs.keys():
            setattr(self, key, kwargs[key])

I want print to represent the object in the following way:

>>> obs = Observable(foo=1, bar=5, _bazz=12, name='Amok', props=('One', 'two'))
>>> print(x)
Observable(bar=5, foo=1, name='Amok', props=('One', 'two'))

I tried to add a custom __repr__:

class Observable(object):
    def __init__(self, **kwargs):
        for key in kwargs.keys():
            setattr(self, key, kwargs[key])

    def __repr__(self):
        atribs = [(atrib,  self.__dict__[atrib]) for atrib in self.__dict__.keys() if not '_' == atrib[0]]
        atrib_strs = []
        for atrib, val in atribs:
            atrib_strs.append('{}={}'.format(atrib, val))

        out_str = '{}({})'.format(self.__class__.__name__, ', '.join(atrib_strs))
        return out_str

For the input above it prints:

Observable(foo=1, bar=5, name=Amok, props=('One', 'two'))

My concern is that I have Amok instead of 'Amok'. I can add a type check for strings, but perhaps there is a way to get a correct string representation of any python type? Maybe a standard library function?

3
  • 1
    I haven't looked into the question but my ocd is killing me to see pytonically instead of Pythonic or Pythonically. Commented Jun 22, 2017 at 7:09
  • @s_vishnu thanks, fixed Commented Jun 22, 2017 at 7:10
  • HAHA fine mate. Wait i'll try for a solution Commented Jun 22, 2017 at 7:10

1 Answer 1

3

A simple way to accomplish this would be to call every attribute's value's __repr__() via repr(). That way, each string representation is guaranteed to be displayed.

>>> class Observable(object):
    def __init__(self, **kwargs):
        for key in kwargs.keys():
            setattr(self, key, kwargs[key])

    def __repr__(self):
        atribs = [(atrib,  self.__dict__[atrib]) for atrib in self.__dict__.keys() if not '_' == atrib[0]]
        atrib_strs = []
        for atrib, val in atribs:
            atrib_strs.append('{}={}'.format(atrib, repr(val))) # add repr() call

        out_str = '{}({})'.format(self.__class__.__name__, ', '.join(atrib_strs))
        return out_str

>>> ob = Observable(foo=1, bar=5, _bazz=12, name='Amok', props=('One', 'two'))
>>> print(ob)
Observable(foo=1, name='Amok', props=('One', 'two'), bar=5)
>>> 
Sign up to request clarification or add additional context in comments.

2 Comments

how about not using dict.keys/getting value and use dict.items/dict.iteritems instead?
@AzatIbrakov Because he doesn't want to include "private" variables in the representation. Although his code could be improved., I didn't really try much.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.