Как сделать целое число больше любого другого целого?
Примечание: в то время как принятый ответ достигает результата, который я хотел, а ответ @ecatmur предоставляет более полный вариант, я считаю очень важным подчеркнуть, что мой вариант использования - это плохая идея в первую очередь. Это объясняется очень хорошо в ответе @Jason Orendorff ниже.
Примечание: этот вопрос не является дубликатом вопроса о sys.maxint
. Он не имеет ничего общего с sys.maxint
; даже в python 2, где sys.maxint
доступен, он НЕ представляет наибольшее целое число (см. принятый ответ).
Мне нужно создать целое число, большее, чем любое другое целое число, что означает объект int
, который возвращает True
по сравнению с любым другим объектом int
, используя >
. Случай использования: функция библиотеки ожидает целое число, и единственный простой способ заставить определенное поведение - передать очень большое целое число.
В python 2 я могу использовать sys.maxint
(изменить: я ошибался). В python 3, math.inf
является ближайшим эквивалентом, но я не могу преобразовать его в int
.
Ответы
Ответ 1
Так как целые числа python неограничены, вы должны сделать это с помощью специального класса:
import functools
@functools.total_ordering
class NeverSmaller(object):
def __le__(self, other):
return False
class ReallyMaxInt(NeverSmaller, int):
def __repr__(self):
return 'ReallyMaxInt()'
Здесь я использовал класс mix-in NeverSmaller
вместо прямого оформления ReallyMaxInt
, потому что на Python 3 действие functools.total_ordering
было бы предотвращено существующими методами упорядочения, унаследованными от int
.
Демонстрация использования:
>>> N = ReallyMaxInt()
>>> N > sys.maxsize
True
>>> isinstance(N, int)
True
>>> sorted([1, N, 0, 9999, sys.maxsize])
[0, 1, 9999, 9223372036854775807, ReallyMaxInt()]
Обратите внимание, что в python2 sys.maxint + 1
больше, чем sys.maxint
, поэтому вы не можете полагаться на это.
Отказ от ответственности: это целое число в смысле OO, оно не является целым числом в математическом смысле. Следовательно, арифметические операции, унаследованные от родительского класса int
, могут не вести себя разумно. Если это вызывает какие-либо проблемы для вашего предполагаемого варианта использования, тогда их можно отключить, реализовав __add__
и друзей, чтобы просто выйти из системы.
Ответ 2
Konsta Vesterinen infinity.Infinity
будет работать (pypi), за исключением того, что он не наследовать от int
, но вы можете подклассифицировать его:
from infinity import Infinity
class IntInfinity(Infinity, int):
pass
assert isinstance(IntInfinity(), int)
assert IntInfinity() > 1e100
Другим пакетом, который реализует значения "бесконечности", является Extremes, который был спасен от отклоненного PEP 326; опять же, вам потребуется подкласс от extremes.Max
и int
.
Ответ 3
Используйте случай: функция библиотеки ожидает целое число, и единственный простой способ заставить определенное поведение - передать очень большое целое число.
Это звучит как недостаток в библиотеке, который должен быть исправлен в его интерфейсе. Тогда все его пользователи выиграют. Что это за библиотека?
Создание магического подкласса int с переопределенными операторами сравнения может сработать для вас. Это хрупкое; вы никогда не знаете, что библиотека собирается делать с этим объектом. Предположим, что он преобразует его в строку. Что должно произойти? И данные, естественно, используются по-разному по мере развития библиотеки; вы можете обновить библиотеку в один прекрасный день, чтобы найти, что ваш трюк больше не работает.
Ответ 4
Мне кажется, что это было бы принципиально невозможно. Скажем, вы пишете функцию, которая возвращает этот RBI ( "действительно большой int" ). Если компьютер способен его хранить, то кто-то другой может написать функцию, которая возвращает одно и то же значение. Ваш RBI больше, чем он сам?
Возможно, вы можете достичь желаемого результата с помощью чего-то вроде ответа @wim: создать объект, который переопределяет операторы сравнения, чтобы сделать "<" всегда возвращайте false, а " > " всегда возвращает true. (Я не написал много Python.В большинстве объектно-ориентированных языков это будет работать, только если сравнение ставит ваше значение в первую очередь, IF RBI > x. Если кто-то пишет сравнение в другую сторону, IF x > RBI, it не удастся, потому что компилятор не знает, как сравнивать целые числа с определенным пользователем классом.)
Ответ 5
В Python 3.5 вы можете:
import math
test = math.inf
И затем:
test > 1
test > 10000
test > x
Всегда будет правдой. Если, конечно, как указано, x также бесконечно или "нан" ( "не число" ).
Как я могу представить бесконечное число в Python?
Отвечено на @WilHall
Ответ 6
Вы не должны наследовать от int
, если вы не хотите как его интерфейса, так и его реализации. (Его реализация представляет собой автоматически расширяющийся набор битов, представляющих конечное число. Вы явно не хотите этого.) Поскольку вам нужен только интерфейс, то наследуйте от ABC Integral
. Благодаря ответу @ecatmur мы можем использовать infinity
для решения проблемы бесконечности (включая отрицание). Вот как мы могли бы объединить infinity
с ABC Integral
:
import pytest
from infinity import Infinity
from numbers import Integral
class IntegerInfinity(Infinity, Integral):
def __and__(self, other):
raise NotImplementedError
def __ceil__(self):
raise NotImplementedError
def __floor__(self):
raise NotImplementedError
def __int__(self):
raise NotImplementedError
def __invert__(self, other):
raise NotImplementedError
def __lshift__(self, other):
raise NotImplementedError
def __mod__(self, other):
raise NotImplementedError
def __or__(self, other):
raise NotImplementedError
def __rand__(self, other):
raise NotImplementedError
def __rlshift__(self, other):
raise NotImplementedError
def __rmod__(self, other):
raise NotImplementedError
def __ror__(self, other):
raise NotImplementedError
def __round__(self):
raise NotImplementedError
def __rrshift__(self, other):
raise NotImplementedError
def __rshift__(self, other):
raise NotImplementedError
def __rxor__(self, other):
raise NotImplementedError
def __trunc__(self):
raise NotImplementedError
def __xor__(self, other):
raise NotImplementedError
def test():
x = IntegerInfinity()
assert x > 2
assert not x < 3
assert x >= 5
assert not x <= -10
assert x == x
assert not x > x
assert not x < x
assert x >= x
assert x <= x
assert -x == -x
assert -x <= -x
assert -x <= x
assert -x < x
assert -x < -1000
assert not -x < -x
with pytest.raises(Exception):
int(x)
with pytest.raises(Exception):
x | x
with pytest.raises(Exception):
ceil(x)
Это можно запустить с помощью pytest
для проверки необходимых инвариантов.
Ответ 7
Другой способ сделать это (очень вдохновленный wim-ответом) может быть объектом, который не бесконечен, но увеличивается на лету по мере необходимости.
Вот что я имею в виду:
from functools import wraps
class AlwaysBiggerDesc():
'''A data descriptor that always returns a value bigger than instance._compare'''
def __get__(self, instance, owner):
try:
return instance._compare + 1
except AttributeError:
return instance._val
def __set__(self, instance, value):
try:
del instance._compare
except AttributeError:
pass
instance._val = value
class BiggerThanYou(int):
'''A class that behaves like an integer but that increases as needed so as to be
bigger than "other" values. Defaults to 1 so that instances are considered
to be "truthy" for boolean comparisons.'''
val = AlwaysBiggerDesc()
def __getattribute__(self, name):
f = super().__getattribute__(name)
try:
intf = getattr(int,name)
except AttributeError:
intf = None
if f is intf:
@wraps(f)
def wrapper(*args):
try:
self._compare = args[1]
except IndexError:
self._compare = 0 # Note: 1 will be returned by val descriptor
new_bigger = BiggerThanYou()
try:
new_bigger.val = f(self.val, *args[1:])
except IndexError:
new_bigger.val = f(self.val)
return new_bigger
return wrapper
else:
return f
def __repr__(self):
return 'BiggerThanYou()'
def __str__(self):
return '1000...'
Что-то вроде этого могло бы избежать много странного поведения, которого можно было бы ожидать. Обратите внимание, что при таком подходе, если в операции задействованы два экземпляра BiggerThanYou
, LHS будет считаться больше, чем RHS.
EDIT: в настоящее время это не работает. Я исправлю это позже. кажется, меня укусят функциональные возможности специальных методов поиска.