【问题标题】:Different results dependent on call of print不同的结果取决于打印调用
【发布时间】:2013-11-10 20:49:48
【问题描述】:

我决定实现一个小的 Huffman 编码脚本。在一个小的概率列表上对其进行测试后,我在构建过程中打印树时得到正确的结果,如果不打印,则得到错误的结果。问题的原因可能是什么?

这是我的代码:

from __future__ import division
import heapq


class LeafNode:
    def __init__(self,symbol,prob):
        self.symbol = symbol
        self.prob = prob
    def __repr__(self):
        return "(%s: %s)" % (self.symbol, self.prob)
class InternalNode:
    def __init__(self,prob,left,right):
        self.prob = prob
        self.left = left
        self.right= right
    def __repr__(self):
        return "(internal : %s)" % (self.prob)

def getDict(seq):
    d = dict()
    for symbol in seq:
        if symbol in d:
            d[symbol] += 1
        else:
            d[symbol] = 1
    return d

def returnProbList(seq):
    data = getDict(seq)
    sum_of_all = sum(data.values())
    l = sorted(data.items(), key=lambda x:x[1])
    return [LeafNode(x[0], x[1]/sum_of_all) for x in l]

def createTree(probs):
    heapq.heapify(probs)
    while len(probs) > 1:
        a = heapq.heappop(probs)
        b = heapq.heappop(probs)
        print a,b #removing this shows wrong results.
        f = InternalNode(a.prob+b.prob,a,b)
        heapq.heappush(probs,f)
    return probs[0]

def printSymbols(tree, seq = ''):    
    if isinstance(tree, InternalNode):
        printSymbols(tree.left, seq+'0')
        printSymbols(tree.right, seq+'1')
    else:
        print tree.symbol, seq

s = "This is some short text I have written. It seems that space is the most common symbol."

#l = returnProbList(s)
l = []
l.append(LeafNode('a4',0.05))
l.append(LeafNode('a3',0.2))
l.append(LeafNode('a2',0.35))
l.append(LeafNode('a1',0.4))



#print l
tree = createTree(l)
printSymbols(tree)

使用 pdb 调试它甚至给了我不同的结果。

#Without print
a4 00
a3 01
a2 10
a1 11
#With print
a1 0
a4 100
a3 101
a2 11
#With pdb
a1 0
a2 10
a3 110
a4 111

【问题讨论】:

    标签: python python-2.7 huffman-code


    【解决方案1】:

    这真的与打印无关。你的问题就在这里:

    heapq.heappush(probs,f)
    

    fInternalNode 类的一个实例,但该类没有定义任何顺序。因此,Python 默认会按内存地址InternalNode 实例进行排序。这根本不是您想要的,内存地址会根据您的其他操作(打印、运行 PDB、创建或删除其他对象...)而有所不同。

    最简单的解决方法是在你的类中添加一个__cmp__ 方法:

        def __cmp__(a, b):
            return cmp(a.prob, b.prob)
    

    那么输出就会一致了。

    编辑:嗯,您还获得了LeafNode 实例的内存地址排序,所以也添加一个__cmp__

    【讨论】:

    • 我从来没有说过打印是原因。我实际上想知道 heapq 怎么知道排序,但我希望 cmp 函数作为参数。感谢您的帮助。
    • 仅供参考,使用(priority, object) 2-tuples 和heapq 可能更常见(有关改进,请参阅文档)。不过,在您的应用程序中,直接比较 .prob 属性(即使用自定义 __cmp__)确实看起来更好。
    • 元组有基于第二个元素的comp方法吗?
    • 序列(包括元组)使用lexicographic comparison。单击此处获取更多说明和示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-13
    • 2023-04-09
    • 2023-03-21
    • 1970-01-01
    • 2018-12-22
    • 1970-01-01
    • 2021-08-20
    相关资源
    最近更新 更多