I have a Python class that stores some fields and has some properties, like
class A(object):
def __init__(self, x, y):
self.x = x
self.y = y
@property
def z(self):
return self.x+1
What changes do I need to make to the class so that I can do
>>> a = A(1,5)
>>> dict(a)
{'y':5, 'z':2}
where I specify that I want to return y
and z
? I can't just use a.__dict__
because it would contain x
but not z
. I would like to be able to specify anything that can be accessed with __getattribute__
.
Add an __iter__()
method to your class that returns an iterator of the object's items as key-value pairs. Then you can pass your object instance directly to the dict()
constructor, as it accepts a sequence of key-value pairs.
def __iter__(self):
for key in "y", "z":
yield key, getattr(self, key)
If you want this to be a little more flexible, and allow the list of attributes to be easily overridden on subclasses (or programmatically) you could store the key list as an attribute of your class:
_dictkeys = "y", "z"
def __iter__(self):
for key in self._dictkeys:
yield key, getattr(self, key)
If you want the dictionary to contain all attributes (including those inherited from parent classes) try:
def __iter__(self):
for key in dir(self):
if not key.startswith("_"):
value = getattr(self, key)
if not callable(value):
yield key, value
This excludes members that start with "_" and also callable objects (e.g. classes and functions).
I think a reasonable approach to this problem would be to create an asdict
method. When you say you want to specify which keys you want the dict to contain, I assume you're happy with that information being passed when the method is called. If that's not what you mean, let me know. (This incorporates kindall's excellent suggestion.)
class A(object):
def __init__(self, x, y):
self.x = x
self.y = y
@property
def z(self):
return self.x+1
def asdict(self, *keys):
if not keys:
keys = ['y', 'z']
return dict((key, getattr(self, key)) for key in keys)
Tested:
>>> A(1, 2).asdict('x', 'y')
{'y': 2, 'x': 1}
>>> A(1, 2).asdict()
{'y': 2, 'z': 2}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With