首页 > 解决方案 > Python中的重载列表理解机制

问题描述

高级问题:比如说,你创建了一个类,它的作用类似于一个列表,但可以快速搜索一个元素,即一个同时索引其内容元素的列表,因此查找特定元素的索引是 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)

...但我喜欢理解机制,我想知道它是否可以应用于创建用户定义的类对象

标签: pythonlistoverloadinglist-comprehension

解决方案


向您添加一个备用构造函数,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))

推荐阅读