Reputation: 26412
Suppose if I have a class as shown below,
class TestClass(object):
def __init__(self):
self.name = 'Marty'
self.age = 25
self.place = 'CL'
@property
def country(self):
return 'USA'
@property
def age_group(self):
return '18-25'
I want to create a dict out of all the @properties. I have tried with __dict__
and vars
but still the @property
is not showing up. How can I include @property
too.
>>> x = TestClass()
>>> x.__dict__
{'age': 25, 'name': 'Marty', 'place': 'CL'}
>>> vars(x)
{'age': 25, 'name': 'Marty', 'place': 'CL'}
I want to include age_group
and country
with the returned values as the keys and values.
Upvotes: 3
Views: 143
Reputation: 55469
You can get the names you want by calling dir
on your instance. However, the list returned by dir
also has a bunch of names you don't want (the names of the methods inherited from object
), so we need to filter those out.
class TestClass(object):
def __init__(self):
self.name = 'Marty'
self.age = 25
self.place = 'CL'
@property
def country(self):
return 'USA'
@property
def age_group(self):
return '18-25'
x = TestClass()
d = {k: getattr(x, k) for k in dir(x) if not k.startswith('__')}
print(d)
output
{'age': 25, 'age_group': '18-25', 'country': 'USA', 'name': 'Marty', 'place': 'CL'}
Here's a cleaner way to do this. We loop over the vars()
of the class object, specifically looking for items that are property
instances. Then we use itertools.chain
to combine those names with the names from calling vars()
on the instance of the class.
from itertools import chain
class TestClass(object):
def __init__(self):
self.name = 'Marty'
self.age = 25
self.place = 'CL'
@property
def country(self):
return 'USA'
@property
def age_group(self):
return '18-25'
def do_stuff(self):
return 'hello'
def attributes_and_properties(obj):
props = (k for k, ktype in vars(type(obj)).items()
if isinstance(ktype, property))
return {k: getattr(obj, k) for k in chain(props, vars(obj))}
x = TestClass()
print(attributes_and_properties(x))
output
{'country': 'USA', 'age_group': '18-25', 'name': 'Marty', 'age': 25, 'place': 'CL'}
This way is superior to the previous technique, since that code will also include bound methods whose names don't start with __
, like do_stuff
, in its output.
Upvotes: 3
Reputation: 3361
Use a dict comprehension that iterates over the objects attributes:
obj = TestClass()
object_dict = {attr: getattr(obj, attr) for attr in dir(obj)}
If you really just want the @property
attributes, which is unclear in your question, you can filter for them like so:
object_properties_dict = {attr: getattr(obj, attr) for attr in dir(obj.__class__) if type(getattr(obj.__class__, attr)) is property}
Upvotes: 3