usar - python bytes to string



¿Por qué un valor falso(0) es más pequeño en bytes que verdadero(1)? (1)

Recuerde que los valores de Python int son de tamaño arbitrario. ¿Cómo funciona?

Bueno, en CPython, 1 un int está representado por un objeto PyLong_Object , que tiene una matriz de fragmentos de 4 bytes 2 , cada uno con un valor de 30 bits 3 del número.

  • 0 no tiene trozos en absoluto.
  • 1 - (1<<30)-1 toma 1 parte.
  • 1<<30 - (1<<60)-1 toma 2 trozos.

Y así.

Esto está ligeramente simplificado; Para más detalles, vea longintrepr.h en la fuente.

En Python 2, hay dos tipos separados, llamados int y long . Un int está representado por un entero 4 con signo de C 32 bits incorporado directamente en el encabezado, en lugar de una matriz de fragmentos. Un long es como un Python 3 int .

Si realiza la misma prueba con 0L , 1L , etc., para solicitar explícitamente valores long , obtendrá los mismos resultados que en Python 3. Pero sin el sufijo L , cualquier literal que encaje en 32 bits le dará un int , y solo los literales que son demasiado grandes te dan long s. 5 (Esto significa que (1<<31)-1 es un int , pero 1<<31 es un long 2 trozos.)

1. En una implementación diferente, esto podría no ser cierto. IIRC, Jython hace más o menos lo mismo que CPython, pero IronPython usa una implementación "bignum" de C #.

2. ¿Por qué 30 bits en lugar de 32? Principalmente porque la implementación de pow y ** puede ser más simple y más rápida si puede suponer que el número de bits en dos "dígitos" es divisible por 10 .

3. Utiliza el C "struct hack" . Técnicamente, un Py_LongObject tiene 28 bytes, pero nadie asigna un Py_LongObject ; Malloc 24, 28, 32, 36, etc. bytes y luego se Py_LongObject * en Py_LongObject * .

4. De hecho, un Python int es un C long , solo para hacer las cosas confusas. Así que la API de C está llena de cosas como PyInt_FromLong donde long significa "32-bit int" y PyLong_FromSize_t donde long significa "bignum".

5. Las primeras versiones de Python 2.x no se integraban int y por long , pero espero que ya nadie tenga que preocuparse por eso.

Estaba jugando con getsizeof() sys y encontré que False (o 0 ) consiste en menos bytes que True (o 1 ). ¿Porqué es eso?

import sys

print("Zero: " + str(sys.getsizeof(0)))
print("One: " + str(sys.getsizeof(1)))
print("False: " + str(sys.getsizeof(False)))
print("True: " + str(sys.getsizeof(True)))

# Prints:
# Zero: 24
# One: 28
# False: 24
# True: 28

De hecho, otros números (también algunos que constan de más de un dígito) son 28 bytes.

for n in range(0, 12):
  print(str(n) + ": " + str(sys.getsizeof(n)))

# Prints:
# 0: 24
# 1: 28
# 2: 28
# 3: 28
# 4: 28
# 5: 28
# 6: 28
# 7: 28
# 8: 28
# 9: 28
# 10: 28
# 11: 28

Aún más: ¡ sys.getsizeof(999999999) también tiene 28 bytes! sys.getsizeof(9999999999) embargo, sys.getsizeof(9999999999) es 32.

Entonces, ¿qué está pasando? Supongo que los valores booleanos True y False se convierten internamente a 0 y 1 respectivamente, pero ¿por qué el tamaño cero es diferente de otros enteros inferiores?

Nota al margen: ¿es esto específico sobre cómo Python representa estos elementos, o es generalmente cómo se presentan los dígitos en el sistema operativo?





cpython