Remarque: bien que la réponse acceptée atteigne le résultat que je voulais et que la réponse @ecatmur offre une option plus complète, je pense qu'il est très important de souligner que mon cas d'utilisation est une mauvaise idée en premier lieu. Ceci est très bien expliqué dans @ Jason Orendorff réponse ci-dessous .
Remarque: cette question n'est pas un doublon de la question sur sys.maxint
. Cela n'a rien à voir avec sys.maxint
; même dans python 2 où sys.maxint
est disponible, il ne représente PAS le plus grand entier (voir la réponse acceptée).
Je dois créer un entier plus grand que tout autre entier, ce qui signifie un objet int
qui renvoie True
par rapport à tout autre objet int
utilisant >
. Cas d'utilisation: la fonction de bibliothèque attend un entier, et le seul moyen facile de forcer un certain comportement est de passer un entier très grand.
En python 2, je peux utiliser sys.maxint
(modifier: j'avais tort). Dans python 3, math.inf
est l'équivalent le plus proche, mais je ne peux pas le convertir en int
.
Puisque python sont illimités, vous devez le faire avec une classe personnalisée:
import functools
@functools.total_ordering
class NeverSmaller(object):
def __le__(self, other):
return False
class ReallyMaxInt(NeverSmaller, int):
def __repr__(self):
return 'ReallyMaxInt()'
Ici, j'ai utilisé une classe de mixage NeverSmaller
plutôt qu'une décoration directe de ReallyMaxInt
, car sur Python 3 l'action de functools.total_ordering
aurait été empêché par les méthodes de classement existantes héritées de int
.
Démo d'utilisation:
>>> N = ReallyMaxInt()
>>> N > sys.maxsize
True
>>> isinstance(N, int)
True
>>> sorted([1, N, 0, 9999, sys.maxsize])
[0, 1, 9999, 9223372036854775807, ReallyMaxInt()]
Notez qu'en python2, sys.maxint + 1
est plus grand que sys.maxint
, vous ne pouvez donc pas vous fier à cela.
Clause de non-responsabilité : il s'agit d'un entier au sens OO , ce n'est pas un entier au sens mathématique. Par conséquent, les opérations arithmétiques héritées de la classe parente int
peuvent ne pas se comporter correctement. Si cela pose des problèmes pour votre cas d'utilisation prévu, ils peuvent être désactivés en implémentant __add__
et mes amis pour faire une erreur.
Konsta Vesterinen infinity.Infinity
fonctionnerait ( pypi ), sauf qu'il n'hérite pas de int
, mais vous pouvez le sous-classer:
from infinity import Infinity
class IntInfinity(Infinity, int):
pass
assert isinstance(IntInfinity(), int)
assert IntInfinity() > 1e100
Extremes , qui a été récupéré du --- PEP 326 ; encore une fois, vous devez sous-classe de extremes.Max
et int
.
Cas d'utilisation: la fonction de bibliothèque attend un entier, et le seul moyen facile de forcer un certain comportement est de passer un entier très grand.
Cela ressemble à une faille dans la bibliothèque qui devrait être corrigée dans son interface. Tous ses utilisateurs en bénéficieraient alors. De quelle bibliothèque s'agit-il?
La création d'une sous-classe int magique avec des opérateurs de comparaison remplacés peut fonctionner pour vous. C'est fragile, cependant; vous ne savez jamais ce que la bibliothèque va faire avec cet objet. Supposons qu'il le convertisse en chaîne. Que doit-il se passer? Et les données sont naturellement utilisées de différentes manières à mesure qu’une bibliothèque évolue; vous pouvez mettre à jour la bibliothèque un jour pour constater que votre astuce ne fonctionne plus.
Il me semble que cela serait fondamentalement impossible. Disons que vous écrivez une fonction qui retourne ce RBI ("really big int"). Si l'ordinateur est capable de le stocker, quelqu'un d'autre pourrait écrire une fonction qui renvoie la même valeur. Votre RBI est-il supérieur à lui-même?
Vous pouvez peut-être obtenir le résultat souhaité avec quelque chose comme la réponse de @ wim: créez un objet qui remplace les opérateurs de comparaison pour que "<" renvoie toujours false et ">" renvoie toujours true. (Je n'ai pas écrit beaucoup de Python. Dans la plupart des langages orientés objet, cela ne fonctionnerait que si la comparaison place votre valeur en premier, IF RBI> x. Si quelqu'un écrit la comparaison dans l'autre sens, IF x> RBI, il échouera car le compilateur ne sait pas comparer les entiers à une classe définie par l'utilisateur.)
Dans Python 3.5, vous pouvez faire:
import math test = math.inf
Et alors:
test > 1 test > 10000 test > x
Sera toujours vrai. Sauf bien sûr, comme indiqué, x est également infini ou "nan" ("pas un nombre").
Comment puis-je représenter un nombre infini en Python?
Répondue par @WilHall
Vous ne devez pas hériter de int
sauf si vous voulez à la fois son interface et son implémentation. (Son implémentation est un ensemble de bits à élargissement automatique représentant un nombre fini. Vous n'en voulez clairement pas.) Puisque vous ne voulez que interface, héritez ensuite de ABC Integral
. Grâce à la réponse de @ ecatmur, nous pouvons utiliser infinity
pour gérer le moindre détail de l'infini (y compris la négation). Voici comment combiner infinity
avec 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)
Cela peut être exécuté avec pytest
pour vérifier les invariants requis.