0

I have a class whose __init__() takes a dictionary parameter. Each key in this dictionary corresponds to an instance variable. The instance variables have default values should we create this object without some or all of the dictionary keys. I have this coded as such:

class MyClass:
    def __init__(self, param1, dict_param):
        self.param1 = param1
        if 'key1' in dict_param:
            self.key1 = dict_param['key1']
        else:
            self.key1 = 10.0  # some default value
        # possibly more instance variable / dictionary key assignments

So this works fine, but in reality I have 8 such dictionary key / class variable assignments and 8 default values.

How can I loop through my dictionary keys and assign them to the instance variables? I'm looking for something like:

class MyClass:
    def __init__(self, param1, dict_param):
        self.param1 = param1
        self.key1 = 10.0  # set default value
        # more defaults...

        for key in dict_param.keys():
            if object has class_variable key:
               assign class_variable param[key]

2 Answers 2

5

Like this:

def __init__(self, param1, dict_param):
    self.param1 = param1
    self.key1 = 10.0  # set default value
    # more defaults...

    for key, value in dict_param.iteritems():
        if hasattr(self, key):
           setattr(self, key, value)

You could also create a dictionary of the default values and use that:

def __init__(self, param1, dict_param):
    self.param1 = param1
    default_vals = {
        'key1': 'default 1',
        'key2': 'default 2',
        'etc': 'and so on'
    }

    for key, value in default_vals.iteritems():
        setattr(self, key, dict_param.get(key, value))

This approach lets you use dict.get to grab the value from dict_param if it exists, or use the value from default_vals if no value is provided in dict_param. Also, depending on where the defaults come from, you could define default_vals at the class level (that is, outside __init__ but inside the class) or globally in the module.

Note that you do not have any class variables here. You have instance variables.

Sign up to request clarification or add additional context in comments.

7 Comments

+1. you could also use **kwargs instead of dict_param if you wanted to pass keys/values as keyword arguments.
In the second code block would 'default_vals = ' not be 'self.default_vals = ' since after you are using setattr(self, ?
@Scott: No. setattr will set the individual attribute (key1, key2, etc.) on self. You could use self.default_vals = ... but then you'd have toi use self.default_vals.iteritems() later. Also this would store the default value dict on each instance in addition to that instance's own values for the individual attributes, which would create a bit of clutter.
@BrenBarn I like the second method you proposed but it will give me a bunch of unresolved attribute references. My code runs because of the defaults or dictionary I pass in. Should I not care about the unresolved attributes or should I set them to None?
@BrenBarn This is the ide (PyCharm) letting me know of possible problems. Since I haven't explicitly named self.key1 in __init__() the ide highlights everywhere that I make use of self.key1. Since your solution has either defaults or dict_param feeding self it all works out and the code runs.
|
1

An alternative - here, __init__ doesn't take a dict but you can send it a dictionary throughout keyword arguments.

>>> class A(object):
...     def __init__(self, key1=10.0, key2=5):
...             self.key1 = key1
...             self.key2 = key2
...
>>> a = A(**{'key2': 3})
>>> a.key1
10.0
>>> a.key2
3

Comments

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.