2011-12-08 82 views
4

我正在研究一个库,该库实现了可以与任何有序数据类型(范围集)一起工作的数据结构。当你允许正面和负面的无限时,许多操作(如倒置)变得有趣。在python中为任何对象创建无穷大和负无穷大

一个目标是让datetime对象与该模块工作,并与非数字对象支持无限大,我创建INFINITY和NEGATIVE_INFINITY:

class _Indeterminate(object): 
    def __eq__(self, other): 
     return other is self 

@functools.total_ordering 
class _Infinity(_Indeterminate): 
    def __lt__(self, other): 
     return False 
    def __gt__(self, other): 
     return True 
    def __str__(self): 
     return 'inf' 
    __repr__ = __str__ 

@functools.total_ordering 
class _NegativeInfinity(_Indeterminate): 
    def __lt__(self, other): 
     return True 
    def __gt__(self, other): 
     return False 
    def __str__(self): 
     return '-inf' 

INFINITY = _Infinity() 
NEGATIVE_INFINITY = _NegativeInfinity() 

不幸的是,这并不为工作datetime对象时,在CMP()操作的左手边:

In [1]: from rangeset import * 
In [2]: from datetime import datetime 
In [3]: now = datetime.now() 
In [4]: cmp(INFINITY, now) 
Out[4]: 1 
In [5]: cmp(now, INFINITY) 
--------------------------------------------------------------------------- 
TypeError         Traceback (most recent call last) 
/home/axiak/Documents/rangeset/<ipython-input-5-c928d3687d92> in <module>() 
----> 1 cmp(now, INFINITY) 

TypeError: can't compare datetime.datetime to _Infinity 

我希望我可以通过使用CMP的包装,只是确保我的对象总是叫绕过这个限制,但我真的想使用.sort() m这将导致在这些对象之间调用cmp。

有没有什么办法可以创建一个比其他任何对象都小得多的对象,并且真的比其他任何对象都要大?

模块主页:https://github.com/axiak/py-rangeset

回答

5

docs

为了去除,以落回 比较对象地址默认方案停止比较也应该意识到,日期比较正常提高TypeError 如果另一个比较不是一个日期对象。但是,如果另一个比较具有 timetuple()属性,则返回NotImplemented而不返回。

因此为了与日期时间对象进行比较,可以添加timetuple方法,例如,

class _Infinity(object): 

    def __lt__(self, other): 
     return False 

    def __gt__(self, other): 
     return True 

    def timetuple(self): 
     return tuple() 

import datetime 
INF = _Infinity() 
now = datetime.datetime.now() 
print cmp(INF, now) 
print cmp(now, INF) 

输出:

1  
-1 
+0

这是正确的答案,谢谢! –

0

我真的不知道,但尝试覆盖__eq____ne__(或__cmp__)看看,只要你做的CMP他们被称为。你认为CMP和__cmp__从蟒蛇3

0

问题是,cmp(now, INFINITY)相当于datetime.__cmp__(INFINITY)其直接限定在datettime类。你可以通过猴子修补日期时间模块来解决这个问题,但那真的很危险。

我想你真正想要的只是一种功能,考虑到你的类,并始终将其置于视无限的符号前面或后面。

def order(x, y): 
    if isinstance(x,_Infinity): 
     return -1 
    if isinstance(y, _Infinity): 
     return 1 
    elif isinstance(x, _NegativeInfinity): 
     return 1 
    elif isinstance(y, _NegativeInfinity): 
     return -1 
    else: 
     return cmp(x,y) 

>>> sorted([datetime.datetime.now(), datetime.datetime.now(), INFINITY, NEGATIVE_INFINITY], cmp=order) 
[ 
    NEGATIVE_INFINITY, 
    datetime.datetime(2011, 12, 8, 13, 38, 47, 428626), 
    datetime.datetime(2011, 12, 8, 13, 38, 47, 428661), 
    INFINITY 
]