【编程学习】利用python实现一个SlashDict

参照完整性

前情提要

最近在互联网遨游的过程中,看到这样的一个题目需求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
>>> sd = SlashDict({'a': {'b': {'c': {'x': 1. 'y': 2}},'d': 3},'e': {'f':{'g': 5}}})

>>> sd['a/b/c']
SlashDict({'x': 1, 'y': 2})

>>> sd['a/d']
3

>>> sd['a/b/k']
KeyError: Dict under key 'a/b' does not have key 'k'

>>> sd.pop('a/b/c/y')
2

>>> sd['e/f/g'] = 5
>>> sd
SlashDict({'a': {'b': {'c': {'x': 1}},'d': 3},'e': {'f':{'g': 5}}})

>>> list(sd.deep_keys(())
['a/b/c/x','a/d', 'e/f/g']

事不宜迟,立马开始实现!

类的内置方法

首先,我们要直到,在定义类时python给我们提供了很多内置方法,能极大地减少我们的工作量:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class MyList:
def __init__(self, l):
self.list = l

def __getitem__(self, key):
return self.list['key']

def __setitem__(self, key, value):
self.list['key'] = value

def __iter__(self):
return iter(self.list)

def __str__(self):
return str(self.list)

def __repr__(self):
return f"MyList({str(self.list)})"

mylist = MyList([1,2,3])

__getitem__:为你的类实现索引,通过设置这个方法,就可以通过mylist[1]的方式索引类中的信息。

__setitem__:为你的类实现索引赋值,通过设置这个方法,就可以通过mylist[1]=8的方式修改类中的信息。

__iter__:使你能够通过for item in mylist:的方法遍历你的类

__str__:当你使用print(mylist),所输出的内容就是该方法的返回值。

__repr__:效果与__str__类似,但是是你在命令行中直接调用mylist所返回的内容

当然,自定义类还有很多内置方法,但是本次实现中没有涉及。

SlashDict实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
class SlashDict(object):
def __init__(self, dic):
self.dict = dic

def __getitem__(self, slash_key):
keys = slash_key.split("/")
dict_now = self.dict
good_keys = []
for key in keys:
if key in dict_now:
dict_now = dict_now[key]
good_keys.append(key)
else:
raise KeyError(f"Dict under key '{'/'.join(good_keys)}' does not have key '{key}'")
if isinstance(dict_now, dict):
return SlashDict(dict_now)
return dict_now

def __setitem__(self, slash_key, value):
keys = slash_key.split("/")
keys_num = len(keys)
dict_now = self.dict
for i in range(keys_num):
key = keys[i]
if i == keys_num - 1:
dict_now[key] = value
break
if key in dict_now:
dict_now = dict_now[key]
else:
dict_now[key] = {}
def __iter__(self):
return iter(self.dict)

def __str__(self):
return str(self.dict)

def __repr__(self):
return f"SlashDict({str(self.dict)})"

def pop(self, slash_key):
keys = slash_key.split("/")
dict_now = self.dict
good_keys = []
for key in keys[0:-1]:
if key in dict_now:
dict_now = dict_now[key]
good_keys.append(key)
else:
raise KeyError(f"Dict under key '{'/'.join(good_keys)}' does not have key '{key}'")

element = dict_now[keys[-1]]
del dict_now[keys[-1]]
return element

def deep_keys(self):
self.deep_keys_list = []
for key in self.dict:
self._key_dfs(key)
return self.deep_keys_list

def _key_dfs(self, key):
if isinstance(self[key], SlashDict):
for key_ in self[key]:
self._key_dfs(f"{key}/{key_}")
else:
self.deep_keys_list.append(key)

接下来,就是依次测试样例需求的内容:

image-20240414162102899

image-20240414162141612

image-20240414162235248

image-20240414162325793

image-20240414162558150

匹配成功,实现有效~~