¿Por qué falla la comparación de bytes con str en Python3?

En Python3 esta expresión se evalúa como False :

 b"" == "" 

mientras que en Python2 esta comparación es True :

 u"" == "" 

La comprobación de la identidad is obviamente, falla en ambos casos.

¿Pero por qué implementarían tal comportamiento en Python3?

En Python 2.x, el objective de diseño para Unicode es permitir operaciones transparentes entre cadenas de Unicode y bytes mediante la conversión implícita entre los 2 tipos. Cuando hace la comparación u"" == "" , el LHS de unicode se codifica automáticamente en una cadena de bytes primero, y luego se compara con el str RHS. Es por eso que devolvió la True .

En contraste, Python 3.x, después de haber aprendido del desorden de Unicode que estaba en Python 2, decidió hacer que todo lo relacionado con las cadenas de unicode y byte sea explícito. Por lo tanto, b"" == "" es False porque la cadena de bytes ya no se convierte automáticamente a Unicode para la comparación.

En Python 3 la cadena es Unicode. El tipo utilizado para contener texto es str y el tipo usado para guardar datos es bytes .

los tipos str y bytes no se pueden mezclar, siempre se debe convertir explícitamente entre ellos. Use str.encode() para pasar de str a bytes, y bytes.decode() para ir de bytes a str.

Por lo tanto, si lo hace b"".decode() == "" obtendrá True :

 >>> b"".decode() == "" True 

Para más información, lea el texto vs. Datos en lugar de Unicode vs. 8-bi

Los diseñadores decidieron no asumir una encoding de coerción al comparar bytes con cadenas, por lo que cae bajo el comportamiento predeterminado de Python 3.x, donde las comparaciones que contienen tipos diferentes fallan.