如何使一个整数大于任何其他整数?
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.Max
和 int
.
继承子类
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
来验证所需的不变量。
注意:虽然接受的答案达到了我想要的结果,并且@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.Max
和 int
.
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
来验证所需的不变量。