Создание бесконечности и отрицательной бесконечности в python для любого объекта - PullRequest
4 голосов
/ 08 декабря 2011

Я работаю над библиотекой, которая реализует структуру данных, которая работает с любым упорядоченным типом данных - диапазоном. Многие из операций (например, инверсия) становятся интересными, если учесть положительную и отрицательную бесконечность.

Одна из целей - заставить объекты 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(), который вызовет вызов cmp между этими объектами. 1010 *

Есть ли способ создать объект, который действительно меньше, чем любой другой объект, и действительно больше, чем любой другой объект?

Модуль home: https://github.com/axiak/py-rangeset

Ответы [ 3 ]

5 голосов
/ 08 декабря 2011

из документов

Для того, чтобы сравнение не вернулось к схеме по умолчанию сравнивая адреса объектов, сравнение даты обычно вызывает TypeError если другой объект не является также объектом даты. Тем не мение, Вместо этого возвращается NotImplemented, если другой компонент имеет Атрибут timetuple ().

, чтобы разрешить сравнение с объектами 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)

выход:

1    
-1
0 голосов
/ 08 декабря 2011

Проблема в том, что cmp(now, INFINITY) эквивалентно datetime.__cmp__(INFINITY), который определяется непосредственно в классе datettime.Вы можете обойти это, исправив модуль dateetime, но это действительно хакерски.

Я думаю, что вы действительно хотите, это просто функция сортировки, которая учитывает ваш класс и всегда помещает его вперед или назад в зависимости отзнак бесконечности.

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
]
0 голосов
/ 08 декабря 2011

Я не совсем уверен, но попробуйте перезаписать __eq__ и __ne__ (или __cmp__), чтобы увидеть, вызываются ли они всякий раз, когда вы делаете cmp.Вы также должны знать, что cmp и __cmp__ удалены из Python 3.

...