注:受け入れられた答えは私が望む結果を達成し、@ ecatmurの答えはより包括的なオプションを提供しますが、そもそもユースケースが悪いアイデアであることを強調することは非常に重要だと感じています。これは @ Jason Orendorffの回答 で非常によく説明されています。
注:この質問は sys.maxint
に関する質問 と重複していません。 sys.maxint
とは関係ありません。 python 2でsys.maxint
が利用可能な場合でも、最大整数を表しません(受け入れられた答えを参照)。
他の整数よりも大きい整数を作成する必要があります。つまり、>
を使用して他のint
オブジェクトと比較したときにTrue
オブジェクトを返すint
オブジェクトを意味します。ユースケース:ライブラリー関数は整数を予期し、特定の動作を強制する唯一の簡単な方法は、非常に大きな整数を渡すことです。
python 2、sys.maxint
を使用できます(編集:私は間違っていました)。python 3、math.inf
が最も近い同等ですが、int
に変換できません。
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__
およびフレンドを実装することでエラーを無効にすることができます。
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
からサブクラス化する必要があります。
ユースケース:ライブラリー関数は整数を予期し、特定の動作を強制する唯一の簡単な方法は、非常に大きな整数を渡すことです。
これはライブラリの欠陥のように聞こえますが、ライブラリのインターフェースで修正する必要があります。その後、そのすべてのユーザーが恩恵を受けるでしょう。それはどの図書館ですか?
オーバーライドされた比較演算子を使用して、魔法のintサブクラスを作成するとうまくいく場合があります。しかし、それはもろいです。ライブラリがそのオブジェクトをどのように処理するかはわかりません。文字列に変換するとします。何が起こるべきですか?また、ライブラリが進化するにつれて、データはさまざまな方法で自然に使用されます。いつかライブラリを更新して、トリックが機能しないことを確認することができます。
これは基本的に不可能であるように思えます。このRBI(「本当に大きなint」)を返す関数を書いたとしましょう。コンピュータがそれを保存できる場合、他の誰かが同じ値を返す関数を書くことができます。あなたのRBIはそれ自体よりも大きいですか?
おそらく、@ wimの答えのようなもので目的の結果を達成できます。比較演算子をオーバーライドするオブジェクトを作成して、「<」が常にfalseを返し、「>」が常にtrueを返すようにします。 (私は多くのPythonを書いたことはありません。ほとんどのオブジェクト指向言語では、RBI> xの場合、比較によって値が最初になった場合にのみ機能します。コンパイラは整数とユーザー定義クラスを比較する方法を知らないため失敗します。)
Python 3.5、you can do:
import math test = math.inf
その後:
test > 1 test > 10000 test > x
常に真実です。もちろん、指摘されているように、xも無限または「nan」(「not a number」)です。
@WilHallによる回答
interfaceとimplementationの両方が必要な場合を除き、int
から継承しないでください。 (その実装は、有限数を表すビットの自動拡張セットです。明らかにそれは必要ありません。)interfaceのみが必要なため、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
で実行して、必要な不変条件を検証できます。