问题描述
高级问题: 比方说,您创建了一个类,它的作用类似于列表,但可以快速搜索元素,即也为其内容元素编制索引的列表,因此查找特定元素的索引是 O(1),而不是 O(n ),就像在标准列表中一样。那么你如何做到以下几点?
class Fast_List():
def __init__(self):
self._list = []
self._index = {}
def __getitem__(self,idx):
return self._list[idx]
def __call__(self,idx):
return self._list[idx]
def append(self,elem):
idx = len(self._list)
self._list.append(elem)
self._index[elem] = idx
def index(self,elem):
return self._index[elem]
al = Fast_List()
al = [i**2 for i in range(1000)]
上面代码的最后一行将创建一个常规列表,而不是一个连续整数平方的 Fast_list。
但是如果我想让它返回理解语句的 Fast_List 版本怎么办
(当然,我在上面的课程中遗漏了一些函数定义,但它不应该使我问的问题变得模糊
现在,当然,我知道我可以简单地使用 for 循环来构建我的 Fast_List
al = Fast_List()
for i in range(1000):
al.append(i**2)
...但是我喜欢理解机制,我想知道它是否可以应用于创建用户定义的类对象
解决方法
向您的 Fast_List
添加一个替代构造函数,并在列表推导的结果上调用它。
class Fast_List():
def __init__(self):
self._list = []
self._index = {}
def __getitem__(self,idx):
return self._list[idx]
def __call__(self,idx):
return self._list[idx]
def append(self,elem):
idx = len(self._list)
self._list.append(elem)
try:
self._index[elem].append(idx)
except KeyError:
self._index[elem] = [idx]
def index(self,elem):
list_idx = self._index[elem]
return list_idx
@classmethod
def from_list(cls,lst):
self = cls()
for el in lst:
self.append(el)
return self
result = Fast_List.from_list([i**2 for i in range(1000)])
现在您可能会说:“当然可以,但我仍在构建列表,然后再将其摄取到 Fast_List
中”,这是真的。但是,出于任何原因,您不需要将其作为列表。更改周围的参数并使用 genexp 代替,突然之间您可以完全省略列表初始化。
# inside Fast_List(),literally just a rename of from_list to from_iterable
# and lst to iterable
@classmethod
def from_iterable(cls,iterable):
self = cls()
for el in iterable:
self.append(el)
return self
# and in the construction,literally just omit the square brackets
result = Fast_List.from_list(i**2 for i in range(1000))
事实上,您可能会注意到,您可以选择以这种方式初始化 Fast_List
!让我们这样做:
class Fast_List():
def __init__(self,iterable=None):
self._list = []
self._index = {}
if iterable is not None:
for el in iterable:
self.append(el)
# the rest of the class is unchanged
result = Fast_List(i**2 for i in range(1000))