注意:虽然接受的答案达到了我想要的结果,并且@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
。
答案 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.Max
和int
继承。
答案 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咬了。