I want to achieve a customized dict that return the items according to an attribute mode
as follows:
class MyDict(dict):
def __init__(self):
super(MyDict, self).__init__()
self.mode = True
mydict = MyDict()
# fill data {0:0, 1:1, 2:2, 3:3, ..., 9:9}
for i in range(10):
mydict[i] = i
mydict.mode
acts as a filter. For example, when mydict.mode
is True
, mydict
works like it only has the first half items, and when mydict.mode
is False
, it only contains the remaining data.
mydict.mode=True
print(mydict) # {0:0, 1:1, 2:2, 3:3, 4:4}
print(mydict.keys()) # [0, 1, 2, 3, 4]
mydict.mode=False
print(mydict) # {5:5, 6:6, 7:7, 8:8, 9:9}
print(mydict.keys()) # [5, 6, 7, 8, 9]
The above code is only a simple example, the support for more complex filters is also expected.
At first, I want to filter items within the functions of dict. The problem is that the class dict in python is implemented by C language rather than python, I don't know which and where is the most original iter function. So I have to rewrite all functions for my customized dict, like keys()
, items()
, values()
, __contains__
, __getitem__
...
Is there any better idea to achieve my customized dict?
CodePudding user response:
I hope this helps you,
mydict = MyDict()
for i in range(11):
mydict[i] = i
mid_index = int(len(mydict.keys()) / 2)
if mydict.mode == True:
new_keys = list(mydict.keys())[:mid_index]
new_values = list(mydict.values())[:mid_index]
new_dict = dict(zip(new_keys, new_values))
print(new_dict)
else:
new_keys = list(mydict.keys())[mid_index:]
new_values = list(mydict.values())[mid_index:]
new_dict = dict(zip(new_keys, new_values))
print(new_dict)
This code first identifies the dictionary's middle key's index and then returns the values according to that.
CodePudding user response:
There's not really a lot that you need to implement - just 3 higher level function (keys, values, items) and 3 dunder functions (setitem, getitem, contains). Add a few helper functions to keep the code concise then you end up with:
class MyDict:
def __init__(self, mode=True):
self._dict = dict()
self._mode = mode
@property
def mode(self):
return self._mode
@mode.setter
def mode(self, mode):
self._mode = mode
def __split(self, list_):
mid = len(self._dict) // 2
return list_[:mid] if self._mode else list_[mid:]
def __sublistK(self):
return self.__split(list(self._dict.keys()))
def __sublistV(self):
return self.__split(list(self._dict.values()))
def __sublistI(self):
return self.__split(list(self._dict.items()))
def keys(self):
for k in self.__sublistK():
yield k
def values(self):
for v in self.__sublistV():
yield v
def items(self):
for k, v in self.__sublistI():
yield k, v
def __setitem__(self, k, v):
self._dict[k] = v
def __getitem__(self, k):
if k in self:
return self._dict[k]
def __contains__(self, k):
return k in self.__sublistK()
Now you can use this as a regular dictionary except that the output will be influenced by the mode value