【问题标题】:TypeError: on heapq.heapop on python3 but but working in python2TypeError:在 python3 上的 heapq.heapop 上,但在 python2 中工作
【发布时间】:2020-08-25 00:01:19
【问题描述】:

我正在研究一种使用各种霍夫曼编码的基因组压缩算法。我在 python2 中有以下代码:

def makeHuffTree(trees):
   heapq.heapify(trees)
   while len(trees) > 1:
      childR, childL = heapq.heappop(trees), heapq.heappop(trees)
      parent = (childL[0] + childR[0], childL, childR)
      heapq.heappush(trees, parent)
   return trees[0]

我正在尝试在 python3 中运行它。但是,我收到如下类型错误:

TypeError: '<' not supported between instances of 'tuple' and 'str'

进入函数的输入是一个元组列表。说,

[(1, '35'), (1, '38'), (1, '50'), (1, 'K'), (4, 'N')]

我很困惑,为什么它在 python 2 中工作但在 python3 中没有。 我尝试调试程序并将其缩小到出现错误的行。 模块heapq的功能如下:

def heappop(heap):
    """Pop the smallest item off the heap, maintaining the heap invariant."""
    lastelt = heap.pop()    # raises appropriate IndexError if heap is empty
    if heap:
        returnitem = heap[0]
        heap[0] = lastelt
        _siftup(heap, 0)
        return returnitem
    return lastelt
def _siftup(heap, pos):
    endpos = len(heap)
    startpos = pos
    newitem = heap[pos]
    # Bubble up the smaller child until hitting a leaf.
    childpos = 2*pos + 1    # leftmost child position
    while childpos < endpos:
        # Set childpos to index of smaller child.
        rightpos = childpos + 1
        if rightpos < endpos and not heap[childpos] < heap[rightpos]:
            childpos = rightpos
        # Move the smaller child up.
        heap[pos] = heap[childpos]
        pos = childpos
        childpos = 2*pos + 1
    # The leaf at pos is empty now.  Put newitem there, and bubble it up
    # to its final resting place (by sifting its parents down).
    heap[pos] = newitem
    _siftdown(heap, startpos, pos)
def _siftdown(heap, startpos, pos):
    newitem = heap[pos]
    # Follow the path to the root, moving parents down until finding a place
    # newitem fits.
    while pos > startpos:
        parentpos = (pos - 1) >> 1
        parent = heap[parentpos]
        if newitem < parent:
            heap[pos] = parent
            pos = parentpos
            continue
        break
    heap[pos] = newitem

在线的siftup函数经过一些迭代后出现错误

        if rightpos < endpos and not heap[childpos] < heap[rightpos]:

我尝试打印 rightposendpos 的类型,但我没有看到 str 的实例 - 每次它只是元组。 使用python2,函数执行成功,经过一些步骤后产生如下结果。

input (trees)= [(1, '35'), (1, '38'), (1, '50'), (1, 'K'), (4, 'N')]

[(1, '35'), (1, '38'), (1, '50'), (1, 'K'), (4, 'N')]
Step 1:
[(1, '50'), (1, 'K'), (4, 'N'), (2, (1, '38'), (1, '35'))]
Step 2:
[(2, (1, '38'), (1, '35')), (4, 'N'), (2, (1, 'K'), (1, '50'))]
Step 3:
[(4, 'N'), (4, (2, (1, 'K'), (1, '50')), (2, (1, '38'), (1, '35')))]
Step 4:
(8, (4, (2, (1, 'K'), (1, '50')), (2, (1, '38'), (1, '35'))), (4, 'N'))
Step 5:

但是 在 python 3 中,经过这么多步骤后出现错误。

input (trees)= [(1, '35'), (1, '38'), (1, '50'), (1, 'K'), (4, 'N')]

[(1, '35'), (1, '38'), (1, '50'), (1, 'K'), (4, 'N')]
Step 1:
[(1, '50'), (1, 'K'), (4, 'N'), (2, (1, '38'), (1, '35'))]
Step 2:
[(2, (1, '38'), (1, '35')), (4, 'N'), (2, (1, 'K'), (1, '50'))]

之后出现错误:“TypeError: 'tuple'和'str'的实例之间不支持'

我寻求帮助,让这段代码在 python3 中工作。

【问题讨论】:

  • 令人惊讶的是,如果我更改输入元组,它也适用于 python3。假设我将最后一个元组从 (4,'N') 更改为 (1,'N')。它工作正常。现在,如果python本身的heapq模块出现错误,我会更加困惑。
  • 问题是由于:python 2 允许在字符串和元组之间进行比较,但 python3 不允许比较。不过,正在寻找解决方法。

标签: python-3.x compression huffman-code genome heapq


【解决方案1】:

所以,我想我已经找到了解决问题的方法。问题是由于:python 2允许在字符串和元组之间进行比较,但python3不允许。

更改第 267 行:

if rightpos < endpos and not heap[childpos] < heap[rightpos]:

if rightpos < endpos and not heap[childpos][0] < heap[rightpos][0]:

和第 212 行:

if newitem < parent:

if newitem[0] < parent[0]:

在图书馆https://github.com/python/cpython/blob/3.8/Lib/heapq.py

解决了我的问题。

我在本地覆盖了函数。

【讨论】:

    猜你喜欢
    • 2018-04-28
    • 2022-07-31
    • 1970-01-01
    • 2015-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-12
    • 1970-01-01
    相关资源
    最近更新 更多