Python int s son objetos que encapsulan el valor numérico real. ¿Podemos jugar con ese valor, por ejemplo, establecer el valor del objeto 1 a 2? ¿Entonces 1 == 2 se convierte en True ?
Si podemos. Pero no hagas esto en casa . En serio, el objeto 1 se usa en muchos lugares y no tengo idea de qué podría romper esto y qué podría hacerle a su computadora. Rechazo toda responsabilidad. Pero me pareció interesante aprender sobre estas cosas.
La función id nos da la dirección de la memoria y el módulo ctypes nos permite jugar con la memoria:
import ctypes ctypes.memmove(id(1) + 24, id(2) + 24, 4) print(1 == 2) x = 40 print(x + 1)Producción:
True 42¡Pruébelo en línea! . Lo intenté allí porque esos sitios tienen que estar protegidos de nuestra piratería de todos modos.
Más explicación / análisis:
El memmove copió el valor del objeto 2 en el objeto 1 . Su tamaño es de 28 bytes cada uno, pero omití los primeros 24 bytes, porque ese es el número de referencias del objeto, la dirección de tipo y el tamaño del valor, como también podemos ver/verificar:
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('reference count: ', ref_count, sys.getrefcount(x)) print('type address: ', type_address, id(type(x))) print('number of digits:', number_of_digits, -(-x.bit_length() // 30)) print('lowest digit: ', lowest_digit, x % 2**30)Salida ( ¡Pruébelo en línea! ):
reference count: 135 138 type address: 140259718753696 140259718753696 number of digits: 1 1 lowest digit: 1 1 El recuento de referencias aumenta con la llamada a getrefcount , pero no sé por qué con 3. De todos modos, ~134 cosas que no sean nosotros hacen referencia al objeto 1 , y potencialmente las estamos estropeando todas, así que... realmente no No intentes esto en casa.
Los "dígitos" se refieren a cómo CPython almacena int s como dígitos en base 2 30 . Por ejemplo, x = 2 ** 3000 tiene 101 de esos dígitos. Salida para x = 123 ** 456 para una mejor prueba:
reference count: 1 2 type address: 140078560107936 140078560107936 number of digits: 106 106 lowest digit: 970169057 970169057En Python 2, hay un enfoque mucho más simple: True y False no están protegidos, por lo que puede asignarles cosas.
>>> True = False >>> (1 == 2) is True TrueSi prefiere no meterse con el contenido real de los objetos int o bool almacenados en caché, puede fingir hacer 1 == 2 así:
>>> 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 ... <stdin>:4: SyntaxWarning: "is" with a literal. Did you mean "=="? >>> sys.displayhook = displayhook >>> 1 2 >>> 1 == 2 True