assert “а” == “a” # lol 19


Python 3, le bonheur d’avoir UTF8 comme encoding par défaut !

En plus, ça ajoute un petit potentiel de lulz.

Par exemple, ceci marche très bien :

def test():
    print('Youpi')
    print('Youpi')

Et ceci…

def test():
    print('Arg')
    print('Arg')

… provoque une syntaxe error !

  File "<stdin>", line 2
       print('Arg')
    ^
SyntaxError: invalid character in identifier

La raison est que la première ligne print(‘Arg’) contient le caractère unicode U+0020, qui est un espace inimprimable, mais pas le même que l’ascii :)

Bon, vous allez-me dire, on pouvait déjà mélanger les tabs et les espaces, s’amuser avec les espaces insécables, ou simplement déclarer manuellement l’encoding et faire pareil…

Allons plus loin. Saviez-vous qu’on pouvait utiliser des caractères non-ASCII dans les identifiants en Python 3 ?

Ceci est donc parfaitement valide :

éôà = 1

Ce qui invite bien entendu a des choses tout à fait amusantes comme :

def аttention():
    print('!')
 
>>> аttention()
!
>>> attention()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'attention' is not defined

En effet, j’ai utilisé le caractère “а” cyrilique comme première lettre, et non le “a” ASCII. Ils n’ont pas le même code :

>>> ord("а"), ord("a")
(1072, 97)
>>> "а" == "a"
False

Quand j’étais au lycée, une bonne blague qu’on faisait aux profs était de faire une capture d’écran du bureau de leur ordi, la mettre en fond d’écran, virer les icônes et régler la barrer des tâches pour se cacher automatiquement. Ils pensaient que leur machine était freezée, et un reboot ne changeait rien. Des heures à s’arracher les cheveux.

Avec les identifiants unicodes je pense qu’on peut retrouver cette merveilleuse créativité avec ses collègues.

19 thoughts on “assert “а” == “a” # lol

  • PocketTiger

    -_-* Sérieusement ?

    Pitié, dites moi qu’il existe une façon simple pour que “a” == “a” renvois True, peut importe les encodages. Une sorte de version wysiwyg de la comparaison de caractères, parce que la c’est n’importe quoi.

  • Sam Post author

    Non parce que ces caractères ne sont pas égaux. Par contre, tu peux utiliser unidecode pour ramener le caractère cyrilique à son caractères ascii le plus proche tout comme tu mettrais toutes tes lettres en minuscules pour les comparer si tu avais différentes casses.

    Cette problématique, n’est, bien entendue, par particulière au langage Python mais tient de la complexité du langage humain, du standard unicode qui en découle et se retrouve dans tous les langages qui le gère.

    En même temps, si je choppe un mec de mon équipe écrire des noms d’identifiant avec des caractères non ascii, je sors le taser.

  • Fred

    >Quand j’étais au lycée, une bonne blague qu’on faisait aux
    >profs était de faire une capture d’écran du bureau de leur
    >ordi, la mettre en fond d’écran, virer les icônes et régler la
    >barrer des tâches pour se cacher automatiquement. Ils
    >pensaient que leur machine était freezée, et un reboot ne
    >changeait rien. Des heures à s’arracher les cheveux.
    Excellent. Quand moi j’étais au lycée, les profs utilisaient des ardoises et des craies. C’était moins marrant et surtout moins facile de leur faire croire que l’ardoise était freezée…

    >Avec les identifiants unicodes je pense qu’on peut retrouver
    >cette merveilleuse créativité avec ses collègues.
    Comme ce serait trop immonde… sauf pour certains qui sont vraiment abrutis et donc, fatalement, qui méritent ;)

  • Fred

    @PocketTiger
    C’est comme si tu demandais de faire en sorte que “0” = “O”. Désolé, si le codage est différent alors les caractères sont différents. C’est un axiome fondamental pour 99% de notre informatique.
    Mais t’en fais pas, tu es aujourd’hui parfaitement à l’aise avec “O” et “0”, demain tu seras tout aussi à l’aise avec “a” et “a”…

  • H3

    >Quand j’étais au lycée, une bonne blague qu’on faisait aux
    >profs était de faire une capture d’écran du bureau de leur
    >ordi, la mettre en fond d’écran, virer les icônes et régler la
    >barrer des tâches pour se cacher automatiquement. Ils
    >pensaient que leur machine était freezée, et un reboot ne
    >changeait rien. Des heures à s’arracher les cheveux.

    Ahah ! Nous on branchait un petit récepteur de souris sans fil sur les bécanes des salles de TP… En faisant juste des petits coups une fois de temps en temps (that’s what she said), c’est la crise de nerf assurée) Des heures de fun en perspective.

  • Sam Post author

    @H3 : pas mal le coup du sans fil. Y a aussi le classique script qui ouvrait le lecteur CD et le fermait toutes les 2 minutes lancé au démarrage…

  • PocketTiger

    @Fred, Oui j’ai bien compris le fond du problème, que les codes des lettres ne sont pas les même. D’ailleurs quand on parle de chaînes de caractère c’est toujours prendre nos rêves pour des réalités. Un “A” n’est jamais qu’un alias, un symbole, vers un nombre.

    J’ai encadré pas mal de jeunes n’ayant jamais ouvert un notepad de leur vie et devant apprendre : le shell-script, le C, le PHP, la logique booléenne, l’arithmétique des pointeurs, la gestion de la mémoire avec malloc, la récursion, la programmation objet, et les expression régulières en 5 semaines.

    L’occasion de franches tranches rigolades et d’un paquet de crise de nerfs. Je sais donc qu’il peut être particulièrement complexe de faire admettre à un débutant que 0 != “0”, que 0 == “” et que “A” == 65.

    Ce qui m’énerve ici, c’est la volonté des gents à réinventer la roue de 36 façon différentes. Je veux dire, il n’existe pas plusieurs version des deux valeur booléenne “True” et “False”, True == True, sera toujours vrais dans tout les langages, pareille pour les valeurs numérique. Deux nombres strictement les mêmes seront toujours égaux, leur comparaisons renvois True. Alors pourquoi doit-on se farcir un tel bordel dans les encodages de textes ?

    Question purement rhétorique bien sûr, je sais bien que la disparité des encodage vient du fait que chacun répond à un besoin précis. Mais ça me fait pleurer qu’il n’y pas plus d’uniformité la dedans et qu’on puisse en arriver à “a” != “a”

  • Goldy

    J’ai quand même été déçu de constater il y a quelques jour qu’on ne pouvait pas faire ça ^^’

    File "caca.py", line 1

  • Goldy

    Tiens, on dirait que les emoji font planter les commentaires :/

    Désolé

  • Sam Post author

    Ouai, wordpress ne gère pas l’unicode correctement. Quelle surprise !

    Mais oui, on ne peut pas faire pileofpoo = 1. J’ai aussi essayé :D

  • Kikoololmdr

    @pockettiger
    Je ne vois pas pourquoi tu parles de différents encodages. Il n’en est pas question ici. Il n’y a qu’un seul encodage : utf-8.
    Il y a plusieurs caractères qui ont la même gueule mais pas le même sens. Et tu ne vas quand même pas mélanger des choses qui sont sémantiquement différentes.
    En plus, ici, c’est un cas “simple”. Mais imagine deux caractères qui sont représentés avec le même glyphe dans une font et avec deux glyphes différentes dans une autre font. T’auras l’air malin si tu donnes tout le temps le même code unicode à ces deux caractères (et dans les maisons d’éditions, on rigole pas avec ce genre de chose).
    Et mettre des limites pour dire que tel ou tel caractères sont identique et doivent avoir le même code, c’est très difficile. Par exemple, vendredi, il y a un stagiaire dans ma boite qui s’est amusé à remplacer les apostrophes et guillemets française par les anglaises sur un gros volume de données. Comme ça, pouf, parce que pour lui, c’est identique, ça a la même tronche sur son éditeur de code. Et ça a râlé très fort (la question du pourquoi un stagiaire bosse sur ce genre de chose est un autre débat, et je n’étais pas d’accord pour ça).

    Si en python, on craint ce genre de truc, on encode son fichier source en ascii/latin-1 (qui ne comprend pas les caractères cyrillique par exemple). Et il t’enverra chier si tu mets n’importe quoi dedans.

  • kontre

    En fait, il y a toute une gamme d’identifiants qui sont classés comme nombres, donc bien sûr 0123456789 font partie. Ils sont traités différemment des autres pour les identifiants (on ne peut pas commencer un identifiant par un nombre). De même certains sont qualifiés comme opérateurs, on ne peut pas les utiliser dans un identifiant, comme le signe divisé (le tiret avec un point au dessus et au dessous).

  • Baronsed

    Est-ce qu’il n’existerait pas une super-fonte qui serait faite spécialement pour faire la différence entre les caractères qui se ressemblent ?

    Par ailleurs, qu’est-ce que vous pensez de la décision d’accepter unicode pour les NDD (moi je crois que c’est une énorme connerie) ?

  • Sam Post author

    Pour le moment, aucune font ne couvre tout unicode de toute manière.

    Quand aux NDD, pour les caractères chinois ou jap, ça a du sens. C’est aussi idiot de demander à 1.5 milliard de personne d’utiliser nos caractères inconpréhensibles pour eux que si on devait tous taper les URLS uniquement en chinois.

  • PocketTiger

    @Kikoololmdr

    imagine deux caractères qui sont représentés avec le même glyphe dans une font et avec deux glyphes différentes dans une autre font.

    Tu me fais du mal, tu le sais ça… ='( Mais je comprend mieux le souci maintenant.

    Ce qu’il faudrait c’est inventer un langage objet de la font. Ou chaque caractère serait une instance de la classe Char.

    Dans cette classe tu à un attribut principal servant à définir l’instance, ce serait une lettre ou un caractère simple du langage, sans accent ni propriété particulière.
    Ensuite tu aurais des propriétés secondaires. Comme secable, case, accent, cedilla, etc.
    Du coup on pourrait comparer un “a” et un “À” de façon stricte, ou souple. Genre “a” == “À” ou “a” === “À”. Et on pourrait savoir tout de suite si un caractère à des propriétés cachées en appelant une méthode du genre “a”. is_secable?. Ça serait beau…

    Enfin je pense qu’il doit y avoir une couille dans mon raisonnement, parce que ça m’a l’air un peu trop simple.

  • Sam Post author

    C’est déjà le cas. Ca marche pour les caractères composés (et https://pypi.python.org/pypi/Unidecode s’en sert), mais pour des caractères qui sont entiers et juste différents, comme notre a, ça n’aide pas. Tu peux pas dire qu’un b ou un d sont des o avec une barre en haut ou en bas, car cela dépend de la fonte.

  • jedema

    Génial,

    Je vais avoir un humour que mes collègues vont apprécier !

    C’est mon premier message alors je tenais à vous remercier. Votre site est génial et étant adepte de Django je l’apprécie encore plus.

Leave a comment

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.