Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Making a read-only property accessible via **vars(some_class)

I often use the idiom '{var_name}'.format(**vars(some_class)).

However, when I use a property, I cannot use this to get the properties value.

Consider this program:

#!/usr/bin/env python

class Foo(object):
    def __init__(self):
        self._bar = None
        self.baz = 'baz here'

    @property
    def bar(self):
        if not self._bar:
            # calculate some value...
            self._bar = 'bar here'
        return self._bar

if __name__ == '__main__':
    foo = Foo()

    # works:
    print('{baz}'.format(**vars(foo)))

    # gives: KeyError: 'bar'
    print('{bar}'.format(**vars(foo)))

Question:

Is there a way to make a properties value accessible via **vars(some_class)?

like image 960
phoibos Avatar asked Sep 04 '13 10:09

phoibos


Video Answer


2 Answers

Short answer: No, it's not possible to use .format(**vars(object)) to do what you want, since properties do not use __dict__ and from vars documentation:

vars(...)

vars([object]) -> dictionary

  • Without arguments, equivalent to locals().
  • With an argument, equivalent to object.__dict__.

However you can achieve what you want using different format specifiers, for example the attribute lookup:

In [2]: '{.bar}'.format(Foo())
Out[2]: 'bar here'

Note that you simply have to add a leading . (dot) to the names and you get exactly what you want.


Side note: instead of using .format(**vars(object)) you should use the format_map method:

In [6]: '{baz}'.format_map(vars(Foo()))
Out[6]: 'baz here'

Calling format_map with a dict argument is equivalent to calling format using the ** notation, but it is more efficient, since it doesn't have to do any kind of unpacking before calling the function.

like image 186
Bakuriu Avatar answered Sep 21 '22 00:09

Bakuriu


Use . notation -

print('{0._bar}'.format(foo))

like image 29
Tim Wakeham Avatar answered Sep 19 '22 00:09

Tim Wakeham