Bra*_*ant 4 python sorting comparison unit-testing python-2.7
我真的可以在如何实现getitem、iter方法或生成器函数方面使用一些帮助来对我创建的类和类容器进行排序。
我创建了一个具有 send_time (datetime) 和 period_length (int) 属性的 Report 类。我还为 Reports 创建了一个 ReportDeque 容器,它继承自 collections.deque。
我需要为类和它的容器添加排序功能。
到目前为止,我已经排序工作正常,但想让 list.sort() 样式正常工作。
sortedList = sorted(list, key=lambda report: report.send_time)
sortedDeque = sorted(deque, key=lambda report: report.send_time)
Run Code Online (Sandbox Code Playgroud)
我正在努力实现Report 中的getitem以及ReportDeque 中的iter和 next 方法。我似乎无法找到使所有这些工作所需的示例。
也许应该使用生成器函数对 collections.deque 容器进行排序。拥有各种生成器以不同方式对双端队列进行排序会很好。
下面是我的测试用例。要在以下代码中运行单元测试,请键入:
python -m unittest test_reports
Run Code Online (Sandbox Code Playgroud)
输出在这篇文章的末尾。
提前致谢...
------------------- test_reports.py 截图 --------------------------
#!/usr/bin/env python
from datetime import datetime
from collections import deque
import unittest
import inspect
class Report(object):
"""
Contains all information contained in a report
"""
def __init__(self, periodStart, periodEnd, sendTime):
self.period_start = periodStart
self.period_end = periodEnd
self.send_time = sendTime
self.send_timestamp = (sendTime - datetime(1970, 1, 1)).total_seconds()
self.period_length = (periodEnd - periodStart).total_seconds()
#def __getitem__(self, key):
class ReportDeque(deque):
"""
Container for processing, sorting Report objects
"""
#def __iter__(self)
#def next(self)
class TestReports(unittest.TestCase):
def setUp(self):
self.list = []
self.deque = ReportDeque()
# send_time 12/4/13, day length report
report = Report(datetime(2013, 12, 3, 0), datetime(2013, 12, 3, 23), datetime(2013, 12, 4, 0))
self.list.append(report)
self.deque.append(report)
# send_time 12/3/13, day length report
report = Report(datetime(2013, 12, 2, 0), datetime(2013, 12, 2, 23), datetime(2013, 12, 3, 0))
self.list.append(report)
self.deque.append(report)
# send_time 12/2/13, day length report
report = Report(datetime(2013, 12, 1, 0), datetime(2013, 12, 1, 23), datetime(2013, 12, 2, 0))
self.list.append(report)
self.deque.append(report)
# sorted with key function works
self.sortedList = sorted(self.list, key=lambda report: report.send_time)
self.sortedDeque = sorted(self.deque, key=lambda report: report.send_time)
def test_sort_deque_send_time(self):
self.print_inspect()
# deque does not have sort method. How to sort it?
self.deque.sort()
firstReport = self.deque[0]
print "send_time {} period_length {}".format(firstReport.send_time, firstReport.period_length)
self.assertEqual(firstReport.send_time, datetime(2013, 12, 2, 0, 0, 0, 0))
def test_sort_list_send_time(self):
self.print_inspect()
# list.sort() not working. How to implement __get_item___?
self.list.sort()
firstReport = self.list[0]
print "send_time {} period_length {}".format(firstReport.send_time, firstReport.period_length)
self.assertEqual(firstReport.send_time, datetime(2013, 12, 2, 0, 0, 0, 0))
def test_sorted_deque_send_time(self):
self.print_inspect()
firstReport = self.sortedDeque[0]
print "send_time {} period_length {}".format(firstReport.send_time, firstReport.period_length)
self.assertEqual(firstReport.send_time, datetime(2013, 12, 2, 0, 0, 0, 0))
def test_sorted_list_send_time(self):
self.print_inspect()
firstReport = self.sortedList[0]
print "send_time {} period_length {}".format(firstReport.send_time, firstReport.period_length)
self.assertEqual(firstReport.send_time, datetime(2013, 12, 2, 0, 0, 0, 0))
def print_inspect(self):
calling_function = inspect.stack()[1][3]
print "\nin {}()".format(calling_function)
if __name__ == "__main__":
unittest.main()
Run Code Online (Sandbox Code Playgroud)
------------------- test_reports.py 截图 --------------------------
$ python -m unittest test_reports
in test_sort_deque_send_time()
E
in test_sort_list_send_time()
send_time 2013-12-04 00:00:00 period_length 82800.0
F
in test_sorted_deque_send_time()
send_time 2013-12-02 00:00:00 period_length 82800.0
.
in test_sorted_list_send_time()
send_time 2013-12-02 00:00:00 period_length 82800.0
.
======================================================================
ERROR: test_sort_deque_send_time (test_reports.TestReports)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test_reports.py", line 51, in test_sort_deque_send_time
self.deque.sort()
AttributeError: 'ReportsDeque' object has no attribute 'sort'
======================================================================
FAIL: test_sort_list_send_time (test_reports.TestReports)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test_reports.py", line 62, in test_sort_list_send_time
self.assertEqual(firstReport.send_time, datetime(2013, 12, 2, 0, 0, 0, 0))
AssertionError: datetime.datetime(2013, 12, 4, 0, 0) != datetime.datetime(2013, 12, 2, 0, 0)
----------------------------------------------------------------------
Ran 4 tests in 0.011s
FAILED (failures=1, errors=1)
Run Code Online (Sandbox Code Playgroud)
首先,您需要使您的 Report 对象具有可比性,这样您就可以在没有显式键的情况下进行订购。您可能应该阅读丰富的比较,但__cmp__会成功。
class Report(object):
"""
Contains all information contained in a report
"""
def __init__(self, periodStart, periodEnd, sendTime):
self.period_start = periodStart
self.period_end = periodEnd
self.send_time = sendTime
self.send_timestamp = (sendTime - datetime(1970, 1, 1)).total_seconds()
self.period_length = (periodEnd - periodStart).total_seconds()
def __cmp__(self, other):
return cmp(self.send_time, other.send_time)
Run Code Online (Sandbox Code Playgroud)
这就是您在测试时通过测试所需的全部内容list.sort()。和 的测试sorted(list)也sorted(deque)应该有效,但有一个问题。由于您是在寻求实现方面的帮助__getitem__,我认为您相信sorted()是在就地进行排序,并且也会就地对双端队列进行排序。这不是它的工作原理。sorted(iterable)将返回一个新的排序列表,其中包含可迭代的项目。
如果您真的想就地对双端队列进行排序deque.sort(),则必须在方法中实现双端队列排序算法才能就地进行排序,而且我不知道哪种算法对双端队列进行排序更有效(我不是即使确定这样做是否有意义),但我认为重建双端队列并利用python非常有效的排序算法可能更容易:
class ReportDeque(deque):
"""
Container for processing, sorting Report objects
"""
def sort(self, *args, **kwargs):
items = [self.pop() for x in xrange(len(self))]
items.sort(*args, **kwargs)
self.extend(items)
Run Code Online (Sandbox Code Playgroud)
这应该让你所有的测试都通过。
更新
如果要period_length在 send_time 相等时用于消歧,只需将其添加到__cmp__,如下所示:
def __cmp__(self, other):
cmp((self.send_time, self.period_length),
(other.send_time, other.period_length))
Run Code Online (Sandbox Code Playgroud)