Python中的重载列表理解机制

Python中的重载列表理解机制,python,list,overloading,list-comprehension,Python,List,Overloading,List Comprehension,高级问题: 比如说,您创建了一个类似于列表的类,但可以快速搜索一个元素,也就是一个也对其内容元素进行索引的列表,以便查找特定元素的索引是O(1),而不是标准列表中的O(n)。那你怎么做呢 class Fast_List(): def __init__(self): self._list = [] self._index = {} def __getitem__(self, idx): return self._list[idx] def __call__(

高级问题: 比如说,您创建了一个类似于列表的类,但可以快速搜索一个元素,也就是一个也对其内容元素进行索引的列表,以便查找特定元素的索引是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)]
上述代码的最后一行将创建连续整数平方的常规列表,而不是快速列表。
但是如果我想让它返回理解语句的快速列表版本怎么办 (当然,我在上面的类中遗漏了一些函数定义,但这不应该掩盖我所问的问题。)

当然,现在我知道我可以简单地使用for循环来构建我的Fast_列表

al = Fast_List()
for i in range(1000):
  al.append(i**2)

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

向您的
快速列表
添加一个替代构造函数,并在列表理解的结果中调用它

class Fast\u List():
定义初始化(自):
self._list=[]
self._索引={}
def uu getitem uu(self,idx):
返回自我列表[idx]
定义呼叫(self,idx):
返回自我列表[idx]
def附加(自我,元素):
idx=len(自我列表)
self.\u list.append(元素)
尝试:
self.\u索引[elem].append(idx)
除KeyError外:
自索引[elem]=[idx]
def索引(自身、要素):
列表\u idx=自索引[elem]
返回列表
@类方法
来自_列表(cls、lst)的def:
self=cls()
对于lst中的el:
self.append(el)
回归自我
result=Fast\u List.from\u List([i**2表示范围内的i(1000)])
现在,您可能会说:“当然可以,但在将列表放入
Fast_list
”之前,我仍在构建列表”,这是真的。但是,您不需要出于任何原因将其作为列表。更改周围的参数并改为使用genexp,突然之间,您可以完全忽略列表初始化

#在Fast_List()中,字面上只是将from_List重命名为from_iterable
#和lst到iterable
@类方法
来自_iterable(cls,iterable)的def:
self=cls()
对于iterable中的el:
self.append(el)
回归自我
#在构造中,字面上省略方括号
结果=快速列表。从列表(范围(1000)内的i**2)
事实上,您可能会注意到,您可以选择以这种方式开始初始化
Fast\u List
!让我们这样做:

class Fast\u List():
定义初始化(self,iterable=None):
self._list=[]
self._索引={}
如果iterable不是None:
对于iterable中的el:
self.append(el)
#班上的其余部分没有变化
结果=快速列表(范围(1000)内i的i**2)

或者,
\uuuuu init\uuuu
方法的可选参数,可以是一个列表,该列表将代码简化为简单的
快速列表([i**2表示范围内的i(1000)])
我真的很感谢您的回答,在我发布问题后,您的答案来得如此之快。但您的解决方案仍然存在一个问题,即先创建一个常规列表,然后将其转换为快速列表。是否有一种直接执行此操作的方法,以避免生成快速列表所需的内存加倍?(看起来Python中的所有东西都可以重载,那么让理解机制重载如何?@ChrisWysocki你读了我的全部答案了吗?我真的预料到了你的问题:)我们得到了答案。你们是最好的!谢谢史密斯先生,没有办法不按照清单来做清单。这就是我们的结构does@juanpa.arrivillaga这里有一个列表理解,它的计算结果不是列表:
[1/x代表范围内的x(666)]
@superbrain在构建列表时遇到错误,但仍在构建列表。@rdas我同意“构造”,但不同意“评估”。@superbrain可能“如果列表完成时没有错误,则始终计算列表”更准确的说法是,但在这一点上,这是令人毛骨悚然的。不管怎样,这都无助于当前的讨论。