Search code examples
pythonpython-class

Assigning dictionary to a class object


What is the difference between the two class definitions below,

class my_dict1(dict):
    def __init__(self, data):
        self = data.copy()
        self.N = sum(self.values)

The above code results in AttributeError: 'dict' object has no attribute 'N', while the below code compiles

class my_dict2(dict):
    def __init__(self, data):
        for k, v in data.items():
             self[k] = v
        self.N = sum(self.values)

For example,

d = {'a': 3, 'b': 5}
a = my_dict1(d) # results in attribute error
b = my_dict2(d) # works fine

Solution

  • By assigning self itself to anything you assign self to a completely different instance than you were originally dealing with, making it no longer the "self". This instance will be of the broader type dict (because data is a dict), not of the narrower type my_dict1. You would need to do self["N"] in the first example for it to be interpreted without error, but note that even with this, in something like:

    abc = mydict_1({})
    

    abc will still not have the key "N" because a completely difference instance in __init__ was given a value for the key "N". This shows you that there's no reasonable scenario where you want to assign self itself to something else.

    In regards to my_dict2, prefer composition over inheritance if you want to use a particular dict as a representation of your domain. This means having data as an instance field. See the related C# question Why not inherit from List?, the core answer is still the same. It comes down to whether you want to extend the dict mechanism vs. having a business object based on it.