兎奔のノート

6962 ワード

Pythonで修正できない辞書を実現する方法

  • collectionsのUserDict
  • を継承
  • 辞書キー値を変更できる方法を書き換え、異常
  • を投げ出す.
    import collections
    
    
    class ImmutableDict(collections.UserDict):
        def __init__(self, *args, **kwargs):
            super(ImmutableDict, self).__init__(*args, **kwargs)
    
        def __setitem__(self, key, value):
            if key in self.keys():
                raise TypeError('Fuck! Immutable dict!')
            else:
                self.data[key] = value
    
        def __delitem__(self, key):
            if key in self.keys():
                raise TypeError('Fuck! Immutable dict!')
            else:
                raise KeyError

    UserDictクラスのソース:
    class UserDict(MutableMapping):
        # Start by filling-out the abstract methods
        def __init__(*args, **kwargs):
            if not args:
                raise TypeError("descriptor '__init__' of 'UserDict' object "
                                "needs an argument")
            self, *args = args
            if len(args) > 1:
                raise TypeError('expected at most 1 arguments, got %d' % len(args))
            if args:
                dict = args[0]
            elif 'dict' in kwargs:
                dict = kwargs.pop('dict')
                import warnings
                warnings.warn("Passing 'dict' as keyword argument is deprecated",
                              DeprecationWarning, stacklevel=2)
            else:
                dict = None
            self.data = {}
            if dict is not None:
                self.update(dict)
            if len(kwargs):
                self.update(kwargs)
        def __len__(self): return len(self.data)
        def __getitem__(self, key):
            if key in self.data:
                return self.data[key]
            if hasattr(self.__class__, "__missing__"):
                return self.__class__.__missing__(self, key)
            raise KeyError(key)
        def __setitem__(self, key, item): self.data[key] = item
        def __delitem__(self, key): del self.data[key]
        def __iter__(self):
            return iter(self.data)
    
        # Modify __contains__ to work correctly when __missing__ is present
        def __contains__(self, key):
            return key in self.data
    
        # Now, add the methods in dicts but not in MutableMapping
        def __repr__(self): return repr(self.data)
        def copy(self):
            if self.__class__ is UserDict:
                return UserDict(self.data.copy())
            import copy
            data = self.data
            try:
                self.data = {}
                c = copy.copy(self)
            finally:
                self.data = data
            c.update(self)
            return c
        @classmethod
        def fromkeys(cls, iterable, value=None):
            d = cls()
            for key in iterable:
                d[key] = value
            return d