使用heapq实现MinHeap时保持状态

时间:2016-11-18 19:42:38

标签: python heap python-3.5

我正在尝试通过连续调用rs12 = which(rs == 12) rs12_pm3 = 1:nrow(dd) %in% c(rs12, rs12 + 1, rs + 2, rs + 3, rs - 1, rs - 2, rs - 3) dd[rs12_pm3, ] 来实现StreamingMedian对象来维持中位数。为此,我还通过get_median()模块实施了MinHeapMaxHeap课程。

我遇到了一个非常奇怪的错误。出于某种原因,当我运行以下命令时:

heapq

我得到以下输出:

print("Before streaming medians", MinHeap(), sep="\t") # is empty

b = StreamingMedian()
b.add_val(5)
b.add_val(100)

assert b.get_median() == 52.5

print("After streaming medians, for MaxHeap", MaxHeap(), sep='\t') # is empty
print("After streaming medians, for MinHeap", MinHeap(), sep='\t') # should be empty
print("After streaming medians, for MinHeap with input", 
      MinHeap([]), sep="\t") # is empty

可以在下面找到类实现。我在Python 3.5.2 :: Anaconda自定义(64位)上运行它。

Before streaming medians        []
After streaming medians, for MaxHeap    []
After streaming medians, for MinHeap    [100]
After streaming medians, for MinHeap with input []

1 个答案:

答案 0 :(得分:0)

问题

问题出现的原因是如何在python中计算默认参数。它们是在第一次调用函数时计算的,之后函数与最初计算的值一起使用。如果默认值是可变的(如列表所示),则会出现问题。

所以MinHeap发生的事情是:

  1. MinHeap最初创建,l参数默认参数已分配给内存地址。
  2. StreamingMedian修改MinHeap self.heap,这与l指向的内容相同。
  3. 再次调用MinHeap时,l已经有一个内存地址,此内存地址将再次使用并与self.heap绑定。
  4. MaxHeap不会发生这种情况,因为:

    1. MaxHeap最初创建,l参数默认参数已分配给内存地址。
    2. _invert_sign创建一个分配给self.heap的新列表。永远不会修改默认参数l
    3. 再次初始化MaxHeap时,l已经有一个内存地址并再次使用,但它从未被修改过,而且构建了另一个副本,因此永远不会修改它。
    4. 解决方案

      而不是:

      class MinHeap(object):
      
      def __init__(self, l=[]):
          self.heap = l
          heapq.heapify(l)
      

      我们应该使用:

      class MinHeap(object):
      
      def __init__(self, l=None):
          if l is None:
              l = []
          self.heap = l
          heapq.heapify(l)
      

      应对MaxHeap

      进行类似的更改