简体   繁体   English

在python中为任何对象创建无穷大和负无穷大

[英]Creating infinity and negative infinity in python for any object

I'm working on a library that implements a data structure that works with any ordered data type--a rangeset. 我正在开发一个库,它实现了一个适用于任何有序数据类型的数据结构 - 一个范围集。 Many of the operations (like inversion) get interesting when you allow for positive and negative infinity. 当你允许正负无限时,许多操作(如反转)会变得有趣。

One goal is to get datetime objects to work with this module, and in supporting infinity with non-numeric objects, I've created INFINITY and NEGATIVE_INFINITY: 一个目标是让datetime对象与该模块一起使用,并且在使用非数字对象支持infinity时,我创建了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()

Unfortunately, this doesn't work for datetime objects when on the left hand side of the cmp() operation: 不幸的是,当在cmp()操作的左侧时,这对datetime对象不起作用:

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

I had hoped I could get around this limitation by using a cmp wrapper that just ensures that my objects are always called, but I really want to use the .sort() method which will cause cmp to be called between these objects. 我曾希望通过使用cmp包装器来解决这个限制,它只能确保我的对象始终被调用,但我真的想使用.sort()方法,这将导致在这些对象之间调用cmp。

Is there any way to create an object which is truly less than any other object, and truly greater than any other object? 有没有办法创建一个真正小于任何其他对象的对象,并且真正比任何其他对象更大?

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

from the docs 来自文档

In order to stop comparison from falling back to the default scheme of comparing object addresses, date comparison normally raises TypeError if the other comparand isn't also a date object. 为了阻止比较回退到比较对象地址的默认方案,如果另一个比较不是日期对象,则日期比较通常会引发TypeError。 However, NotImplemented is returned instead if the other comparand has a timetuple() attribute. 但是,如果另一个comparand具有timetuple()属性,则返回NotImplemented。

so to allow comparison with datetime objects add a timetuple method eg 所以为了与datetime对象进行比较,可以添加一个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)

output: 输出:

1    
-1

I'm not really sure but try to overwrite __eq__ and __ne__ (or __cmp__ ) to see if they are called whenever you do cmp. 我不太确定但是尝试覆盖__eq____ne__ (或__cmp__ )以查看它们是否在您执行cmp时被调用。 You also should be aware that cmp and __cmp__ is removed from python 3. 您还应该知道从python 3中删除了cmp和__cmp__

Problem is that cmp(now, INFINITY) is equivalent to datetime.__cmp__(INFINITY) which is defined directly on the datettime class. 问题是cmp(now, INFINITY)等同于datetime.__cmp__(INFINITY) ,它直接在datettime类上定义。 You could get around this by monkey-patching the dateetime module but thats really hackish. 你可以通过猴子修补dateetime模块来解决这个问题,但那确实是个hackish。

I think what you really want is just a sort function which takes into account your class and always puts it in front or back depending on the sign of the infinity. 我认为你真正想要的只是一个排序函数,它考虑到你的类,并始终根据无穷大的符号将它放在前面或后面。

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
]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM