Subclassing Python dictionary to override __setitem__

后端 未结 4 1902
别跟我提以往
别跟我提以往 2020-11-28 04:10

I am building a class which subclasses dict, and overrides __setitem__. I would like to be certain that my method will be called in all instances w

4条回答
  •  离开以前
    2020-11-28 04:55

    I found Ian answer and comments very helpful and clear. I would just point out that maybe a first call to the super-class __init__ method might be safer, when not necessary: I recently needed to implement a custom OrderedDict (I'm working with Python 2.7): after implementing and modifying my code according to the proposed MyUpdateDict implementation, I found out that by simply replacing

    class MyUpdateDict(dict):
    

    with:

    from collections import OrderedDict
    class MyUpdateDict(OrderedDict):
    

    then the test code posted above failed:

    Traceback (most recent call last):
    File "Desktop/test_updates.py", line 52, in 
        my_dict = MyUpdateDict([('b',2),('c',3)],a=1)
    File "Desktop/test_updates.py", line 5, in __init__
        self.update(*args, **kwargs)
    File "Desktop/test_updates.py", line 18, in update
        self[key] = other[key]
    File "Desktop/test_updates.py", line 9, in __setitem__
        super(MyUpdateDict, self).__setitem__(key, value)
    File "/usr/lib/python2.7/collections.py", line 59, in __setitem__
        root = self.__root
    AttributeError: 'MyUpdateDict' object has no attribute '_OrderedDict__root'
    

    Looking at collections.py code it turns out that OrderedDict needs its __init__ method to be called in order to initialize and setup necessary custom attributes.

    Therefore, by simply adding a first call to the super __init__ method,

    from collections import OrderedDict
    class MyUpdateDict(Orderedict):
    def __init__(self, *args, **kwargs):
        super(MyUpdateDict, self).__init__() #<-- HERE call to super __init__
        self.update(*args, **kwargs)
    

    we have a more general solution which apparently works for both dict and OrderedDict.

    I cannot state if this solution is generally valid, because I tested it with OrderedDict only. However, it is likely that a call to the super __init__ method is either harmless or necessary rather than harmful, when trying to extend other dict subclasses

提交回复
热议问题