我是Python的新手,所以请为愚蠢的错误辩解... 我正在尝试使用python(2.7.15)中的堆创建优先级队列,但是我的代码显然无法正常工作。
pq = [] # list of entries arranged in a heap
entry_finder = {} # mapping of tasks to entries
REMOVED = '<removed-task>' # placeholder for a removed task
count = 0 # unique sequence count
def push(pq,task,priority=0):
'Add a new task'
count = count+1
entry = [priority, count, task]
entry_finder[task] = entry
heappush(pq, entry)
def update(pq,task, priority=0):
'Add a new task or update the priority of an existing task'
if task in entry_finder:
remove_task(task)
count = count+1
entry = [priority, count, task]
entry_finder[task] = entry
heappush(pq, entry)
def remove_task(task):
'Mark an existing task as REMOVED. Raise KeyError if not found.'
entry = entry_finder.pop(task)
entry[-1] = REMOVED
def pop(pq):
'Remove and return the lowest priority task. Raise KeyError if empty.'
while pq:
priority, count, task = heappop(pq)
if task is not REMOVED:
del entry_finder[task]
return task
raise KeyError('pop from an empty priority queue')
def IsEmpty(pq):
if not pq:
print("List is empty")
这就是我所做的,其中大多数都被放在这里:https://docs.python.org/2/library/heapq.html。 我的问题是当我尝试在python interprenter上运行它时,我得到了:
>>> pq=[]
>>> pq.push("task1",1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute 'push'
我的问题是我该怎么做才能避免此错误,并且我的代码是否存在可能导致进一步错误的缺陷?
答案 0 :(得分:1)
您正在以“面向对象的C”样式构建类,该类涉及将对象上下文传递到函数中,例如do_something(instance, arg)
。这是可行的,但对Python来说不是自然的,Python支持类和一个名为self
的关键字,该关键字代表对象的实例,允许您像调用{{ 1}}功能。
使用这种方法,一个类将封装您当前在全局范围内拥有的所有状态数据:
instance.do_something(arg)
即使以“ C”样式编写,程序在这些全局变量之外也没有实例状态;您需要某种结构来将这些变量保持在一起并将它们传递给函数,或者对每个函数中的每个变量使用push
关键字,这在状态安全方面不是一个很好的解决方案,可重用性,可理解性或任何其他设计指标。
以下是该程序重构为类的示例:
pq = [] # list of entries arranged in a heap
entry_finder = {} # mapping of tasks to entries
REMOVED = '<removed-task>' # placeholder for a removed task
count = 0 # unique sequence count
完成此操作后,您现在可以将类导入到解释器中(确保源代码位于同一文件夹global
中),创建该类的实例并开始使用它:
from heapq import heappush, heappop
class PQ:
def __init__(self):
self.pq = []
self.entry_finder = {}
self.REMOVED = '<removed-task>'
self.count = 0
def push(self, task, priority=0):
'''Add a new task
'''
self.count += 1
entry = [priority, self.count, task]
self.entry_finder[task] = entry
heappush(self.pq, entry)
def update(self, task, priority=0):
'''Add a new task or update the priority of an existing task
'''
if task in self.entry_finder:
self.remove_task(task)
self.count += 1
entry = [priority, self.count, task]
self.entry_finder[task] = entry
heappush(self.pq, entry)
def remove_task(self, task):
'''Mark an existing task as REMOVED. Raise KeyError if not found.
'''
entry = self.entry_finder.pop(task)
entry[-1] = self.REMOVED
def pop(self):
'''Remove and return the lowest priority task. Raise KeyError if empty.
'''
while self.pq:
priority, count, task = heappop(self.pq)
if task is not self.REMOVED:
del self.entry_finder[task]
return task
raise KeyError('pop from an empty priority queue')
def empty(self):
return len(self.pq) == 0
另一种常见的做法是使用pq.py
条件:直接将测试添加到类文件中:
>>> from pq import PQ
>>> pq = PQ()
>>> pq.push(1, 20)
>>> pq.push(2, 30)
>>> pq.push(3, 10)
>>> while not pq.empty(): print pq.pop()
...
3
1
2
>>>
这可以在带有if __name__ == '__main__':
的终端上运行。
答案 1 :(得分:0)
定义push
函数的方式,您需要将代表队列的列表作为第一个参数传递:
代替
pq = [] pq.push("task1", 1)
做
pq = []
push(pq, "task1", 1)