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

时间:2016-10-04 03:00:57

标签: python python-3.x infinity

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

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

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

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

7 个答案:

答案 0 :(得分:67)

由于python整数是无界的,你必须使用自定义类:

import functools

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

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

我在这里使用了混合类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__和朋友来禁用它们,只是出错。

答案 1 :(得分:27)

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.Maxint继承。

答案 2 :(得分:16)

  

用例:库函数需要一个整数,强制某种行为的唯一简单方法是传递一个非常大的整数。

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

使用重写的比较运算符创建一个神奇的int子类可能对您有用。但它很脆弱;你永远不知道图书馆将对该对象做什么。假设它将其转换为字符串。应该怎么办?随着图书馆的发展,数据自然会以不同的方式使用;你有一天可能会更新图书馆,发现你的技巧不再适用了。

答案 3 :(得分:1)

在我看来,这根本不可能。让我们假设您编写了一个返回此RBI的函数("非常大的int")。如果计算机能够存储它,那么其他人可以编写一个返回相同值的函数。你的RBI是否比自己更大?

也许你可以用@ wim的答案来达到预期的效果:创建一个覆盖比较运算符的对象来制作"<"总是返回false和">"总是回归真实。 (我还没有编写很多Python。在大多数面向对象的语言中,只有当比较将你的值放在首位,IF RBI> x时,这才有效。如果有人用另一种方式写比较,IF x> RBI ,它会失败,因为编译器不知道如何将整数与用户定义的类进行比较。)

答案 4 :(得分:1)

  

在Python 3.5中,您可以执行以下操作:

     

import math test = math.inf

     

然后:

     

test > 1 test > 10000 test > x

     

永远都是真的。当然,除非指出,x也是无穷大或“南”(“不是数字”)。

How can I represent an infinite number in Python?

@WilHall回答

答案 5 :(得分:0)

除非您想要接口及其实现,否则不应继承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一起运行,以验证所需的不变量。

答案 6 :(得分:-4)

另一种方法(非常受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咬了。