Вы создаете класс в "объектно-ориентированном C" -стиле, который включает передачу контекста объекта в функцию, например, do_something(instance, arg)
.Это возможно, но не является естественным для Python, который поддерживает классы и ключевое слово с именем self
, которое представляет экземпляр объекта, позволяя написать instance.do_something(arg)
, как вы делали, когда вызывали свою функцию 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
Даже так, как написано в стиле "C"программа не имеет состояния экземпляра вне этих глобальных переменных;вам понадобится какая-то структура, чтобы хранить эти переменные вместе и передавать их в функции, или использовать ключевое слово 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__':
условно:
if __name__ == '__main__':
pq = PQ()
pq.push(1, 20)
pq.push(2, 30)
pq.push(3, 10)
while not pq.empty():
print pq.pop()
Это можно запустить на терминале с помощью python pq.py
.
Попробуйте!