Is it possible to create an object from a dictionary in python in such a way that each key is an attribute of that object?
Something like this:
d =
Why not just use attribute names as keys to a dictionary?
class StructMyDict(dict):
def __getattr__(self, name):
try:
return self[name]
except KeyError as e:
raise AttributeError(e)
def __setattr__(self, name, value):
self[name] = value
You can initialize with named arguments, a list of tuples, or a dictionary, or individual attribute assignments, e.g.:
nautical = StructMyDict(left = "Port", right = "Starboard") # named args
nautical2 = StructMyDict({"left":"Port","right":"Starboard"}) # dictionary
nautical3 = StructMyDict([("left","Port"),("right","Starboard")]) # tuples list
nautical4 = StructMyDict() # fields TBD
nautical4.left = "Port"
nautical4.right = "Starboard"
for x in [nautical, nautical2, nautical3, nautical4]:
print "%s <--> %s" % (x.left,x.right)
Alternatively, instead of raising the attribute error, you can return None for unknown values. (A trick used in the web2py storage class)
Setting attributes in this way is almost certainly not the best way to solve a problem. Either:
You know what all the fields should be ahead of time. In that case, you can set all the attributes explicitly. This would look like
class Employee(object):
def __init__(self, name, last_name, age):
self.name = name
self.last_name = last_name
self.age = age
d = {'name': 'Oscar', 'last_name': 'Reyes', 'age':32 }
e = Employee(**d)
print e.name # Oscar
print e.age + 10 # 42
or
You don't know what all the fields should be ahead of time. In this case, you should store the data as a dict instead of polluting an objects namespace. Attributes are for static access. This case would look like
class Employee(object):
def __init__(self, data):
self.data = data
d = {'name': 'Oscar', 'last_name': 'Reyes', 'age':32 }
e = Employee(d)
print e.data['name'] # Oscar
print e.data['age'] + 10 # 42
Another solution that is basically equivalent to case 1 is to use a collections.namedtuple
. See van's answer for how to implement that.
Sure, something like this:
class Employee(object):
def __init__(self, initial_data):
for key in initial_data:
setattr(self, key, initial_data[key])
Update
As Brent Nash suggests, you can make this more flexible by allowing keyword arguments as well:
class Employee(object):
def __init__(self, *initial_data, **kwargs):
for dictionary in initial_data:
for key in dictionary:
setattr(self, key, dictionary[key])
for key in kwargs:
setattr(self, key, kwargs[key])
Then you can call it like this:
e = Employee({"name": "abc", "age": 32})
or like this:
e = Employee(name="abc", age=32)
or even like this:
employee_template = {"role": "minion"}
e = Employee(employee_template, name="abc", age=32)
You can access the attributes of an object with __dict__
, and call the update method on it:
>>> class Employee(object):
... def __init__(self, _dict):
... self.__dict__.update(_dict)
...
>>> dict = { 'name': 'Oscar', 'lastName': 'Reyes', 'age':32 }
>>> e = Employee(dict)
>>> e.name
'Oscar'
>>> e.age
32
I think that answer using settattr
are the way to go if you really need to support dict
.
But if Employee
object is just a structure which you can access with dot syntax (.name
) instead of dict syntax (['name']
), you can use namedtuple like this:
from collections import namedtuple
Employee = namedtuple('Employee', 'name age')
e = Employee('noname01', 6)
print e
#>> Employee(name='noname01', age=6)
# create Employee from dictionary
d = {'name': 'noname02', 'age': 7}
e = Employee(**d)
print e
#>> Employee(name='noname02', age=7)
print e._asdict()
#>> {'age': 7, 'name': 'noname02'}
You do have _asdict()
method to access all properties as dictionary, but you cannot add additional attributes later, only during the construction.
say for example
class A():
def __init__(self):
self.x=7
self.y=8
self.z="name"
if you want to set the attributes at once
d = {'x':100,'y':300,'z':"blah"}
a = A()
a.__dict__.update(d)