funcion - ¿Es seguro desactivar un solo bit en indicadores con enteros de longitud variable de Python?
string to binary python (2)
En mi programa (escrito en Python 3.4) tengo una variable que contiene varias banderas, por ejemplo:
FLAG_ONE = 0b1
FLAG_TWO = 0b10
FLAG_THREE = 0b100
status = FLAG_ONE | FLAG_TWO | FLAG_THREE
Establecer otra bandera se puede hacer fácilmente con
status |= FLAG_FOUR
Pero, ¿y si explícitamente quiero borrar una bandera? Lo haría
status &= ~FLAG_THREE
¿Es este enfoque seguro? Como el tamaño de un entero en Python no está definido, ¿qué FLAG_THREE
si el status
y FLAG_THREE
difieren en tamaño?
(El status
debe ser un campo de bits porque necesito este valor para un protocolo de hardware).
Borrar una bandera trabaja con
status &= ~FLAG_THREE
porque Python trata esos valores negados como negativos:
>>> ~1L
-2L
>>> ~1
-2
>>> ~2
-3
Así, el &
el operador puede actuar de manera adecuada y producir el resultado deseado, independientemente de la longitud de los operandos, por lo 0b11111111111111111111111111111111111111111111111111111111111 & ~1
funciona bien, aunque el operando de la izquierda es biffer que el de la derecha.
Sin embargo, en la otra dirección (RH más larga que LH), funciona, ya que tener un número excesivo de 1
bits no importa.
Deberías estar seguro usando ese enfoque, sí.
~
en Python se implementa simplemente como -(x+1)
(consulte la fuente de CPython ) y los números negativos se tratan como si tuvieran cualquier número requerido de 1s que rellenen el inicio. De la Wiki de Python :
Por supuesto, Python no usa números de 8 bits. SE UTILIZÓ para usar, sin embargo, muchos bits eran nativos de su máquina, pero como no era portátil, recientemente se cambió a un número INFINITO de bits. Por lo tanto, el número -5 es tratado por operadores bit a bit como si estuviera escrito "... 1111111111111111111011".
En otras palabras, con bitwise y &
está garantizado que esos 1s ajustarán la longitud de ~FLAG
(un entero negativo) a la longitud del status
. Por ejemplo:
100000010000 # status
& ~10000 # ~FLAG
es tratado como
100000010000
& 111111101111
= 100000000000 # new status
Este comportamiento se describe en un comentario en la fuente here .