Les int
s en Python sont objets qui encapsulent la valeur numérique réelle. Par curiosité / pour le fun, je me demandais : pouvons-nous modifier cette valeur, par exemple en définissant la valeur de l'objet 1
à 2 ? Ainsi, 1 == 2
devient True
?
Réponses
Trop de publicités?Oui nous le pouvons. Mais ne faites pas ça chez vous. Sérieusement, l'objet 1
est utilisé à de nombreux endroits et je n'ai aucune idée de ce que cela pourrait casser et de ce que cela pourrait faire à votre ordinateur. Je rejette toute responsabilité. Mais j'ai trouvé cela intéressant d'apprendre sur ces choses.
La fonction id
nous donne l'adresse mémoire et le module ctypes
nous permet de manipuler la mémoire :
import ctypes
ctypes.memmove(id(1) + 24, id(2) + 24, 4)
print(1 == 2)
x = 40
print(x + 1)
Résultat :
Vrai
42
Essayez en ligne !. Je l'ai essayé là-bas parce que de tels sites doivent de toute façon être protégés contre nos piratages.
Plus d'explication / analyse :
Le memmove
a copié la valeur de l'objet 2
dans l'objet 1
. Leur taille est de 28 octets chacun, mais j'ai sauté les 24 premiers octets car il s'agit du compteur de référence de l'objet, de l'adresse du type et de la taille de la valeur, comme nous pouvons le voir/vérifier également :
import ctypes, struct, sys
x = 1
data = ctypes.string_at(id(x), 28)
ref_count, type_address, number_of_digits, lowest_digit = \
struct.unpack('qqqi', data)
print('compteur de référence : ', ref_count, sys.getrefcount(x))
print('adresse du type : ', type_address, id(type(x)))
print('nombre de chiffres : ', number_of_digits, -(-x.bit_length() // 30))
print('chiffre le plus bas : ', lowest_digit, x % 2**30)
Résultat (ints sous forme de :</p>
<pre><code>compteur de référence : 135 138
adresse du type : 140259718753696 140259718753696
nombre de chiffres : 1 1
chiffre le plus bas : 1 1
</code></pre>
<p>Le compteur de référence est augmenté par l'appel de <code>getrefcount</code>, je ne sais pas pourquoi de 3. Quoi qu'il en soit, environ 134 choses autres que nous référencent l'objet <code>1</code>, et nous pourrions potentiellement tous les perturber, donc... vraiment ne faites pas ça chez vous.</p>
<p>Les ) chiffres en base 230. Par exemple, x = 2 ** 3000
a 101 de ces chiffres. Résultat pour x = 123 ** 456
pour un meilleur test :
compteur de référence : 1 2
adresse du type : 140078560107936 140078560107936
nombre de chiffres : 106 106
chiffre le plus bas : 970169057 970169057
Si vous préférez ne pas vous occuper des contenus réels des objets int
ou bool
mis en cache, vous pouvez simuler un 1 == 2
de cette manière :
>>> import builtins
>>> import sys
>>>
>>> def displayhook(value):
... if value is False:
... value = True
... elif value is 1:
... value = 2
... text = repr(value)
... sys.stdout.write(text)
... sys.stdout.write('\n')
... builtins._ = value
...
:4: SyntaxWarning: "is" with a literal. Did you mean "=="?
>>> sys.displayhook = displayhook
>>> 1
2
>>> 1 == 2
True