如何使一个整数大于任何其他整数?

How to make an integer larger than any other integer?

注意:虽然接受的答案达到了我想要的结果,并且@ecatmur 的答案提供了一个更全面的选项,但我觉得强调我的用例首先是一个坏主意是非常重要的。这在 .

中有很好的解释

注意:此问题与 the question about sys.maxint 不重复。与sys.maxint无关;即使在 python 2 中 sys.maxint 可用,它也不表示最大整数(请参阅已接受的答案)。

我需要创建一个比任何其他整数都大的整数,这意味着 int 对象 returns True 与任何其他 int 对象相比使用 >。用例:库函数需要一个整数,强制执行某种行为的唯一简单方法是传递一个非常大的整数。

在python 2中,我可以使用sys.maxint(编辑:我错了)。在 python 3 中,math.inf 是最接近的等价物,但我无法将其转换为 int

由于 python 整数是无界的,因此您必须使用自定义 class:

import functools

@functools.total_ordering
class NeverSmaller(object):
    def __le__(self, other):
        return False

class ReallyMaxInt(NeverSmaller, int):
    def __repr__(self):
        return 'ReallyMaxInt()'

这里我使用了混入classNeverSmaller而不是直接修饰ReallyMaxInt,因为在Python3上[=14=的动作] 会被继承自 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意义上的整数,不是数学意义上的整数。因此,从父级 class int 继承的算术运算可能无法正常运行。如果这会导致您的预期用例出现任何问题,那么可以通过实施 __add__ 和朋友们来禁用它们,只是出错。

在我看来,这根本不可能。假设您编写了一个 return 这个 RBI ("really big int") 的函数。如果计算机能够存储它,那么其他人可以编写一个 return 具有相同值的函数。您的 RBI 大于自身吗?

也许您可以通过类似@wim 的回答获得预期的结果:创建一个覆盖比较运算符的对象,使“<”始终return 为假,“>”始终return 为真. (我没有写很多 Python。在大多数面向对象的语言中,这只有在比较将你的值放在第一位时才有效,IF RBI>x。如果有人以另一种方式编写比较,IF x >RBI,它会失败,因为编译器不知道如何将整数与用户定义的 class 进行比较。)

Konsta Vesterinen 的 infinity.Infinity would work (pypi),除了它不继承自 int,但您可以将其子类化:

from infinity import Infinity
class IntInfinity(Infinity, int):
    pass
assert isinstance(IntInfinity(), int)
assert IntInfinity() > 1e100

另一个实现 "infinity" 值的包是 Extremes, which was salvaged from the rejected PEP 326;同样,您需要从 extremes.Maxint.

继承子类

Use case: library function expects an integer, and the only easy way to force a certain behavior is to pass a very large integer.

这听起来像是库中的一个缺陷,应该在其界面中修复。那么它的所有用户都会受益。这是什么图书馆?

使用重写的比较运算符创建一个神奇的 int 子类可能适合您。不过它很脆;您永远不知道库将如何处理该对象。假设它将其转换为字符串。应该发生什么?随着图书馆的发展,数据自然会以不同的方式使用;你可能有一天更新了库,发现你的把戏不再奏效了。

执行此操作的另一种方法(非常受 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。

编辑:目前这不起作用-我稍后会修复它。我好像被special method lookup functionality咬了。

In Python 3.5, you can do:

import math test = math.inf

And then:

test > 1 test > 10000 test > x

Will always be true. Unless of course, as pointed out, x is also infinity or "nan" ("not a number").

How can I represent an infinite number in Python?

@WilHall 回答

你不应该从 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 来验证所需的不变量。