Tim-ats

Articles

Bidouillage avec les opérateurs shift

Les opérateurs << et >> sont relativement méconnus en Python. On les nomme respectivement right-shift et left-shift.

En réalité, ce sont des opérateurs binaires, ils permettent de décaler tous les bits d'un nombre vers la droite ou la gauche en éliminant n bit.

Ainsi :

>>> bin(128)
'0b10000000'
>>> 128 >> 1
64
>>> bin(64)
'0b1000000'

Et :

>>> bin(16)
'0b10000'
>>> 16 << 2
64
>>> bin(64)
'0b1000000'

Finalement, un "left shift" de n bits revient à mulitplier l'opérande de gauche par 2n.

>>> (8*pow(2, 3)) == (8 << 3)
True

Attention, utiliser un nombre négatif comme second opérande provoque une erreur :

>>> 8 << -1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: negative shift count

Nonobstant, ce comportement est rarement utile. Heureusement, tous les opérateurs de Python sont overridables.

Et c'est là que ça devient intéressant.

S'approcher de la magie noire de Bash

Pour ajouter à la fin du fichier file.txt la chaîne de caractère "Hello world" en bash, on ferait :

echo "Hello world" >> file.txt

Pour reproduire ce comportement en Python, une approche naïve pourrait consister à faire :

class File:

    def __init__(self, filename: str):
        self.file = filename

    def __lshift__(self, shift: str):
        """Override l'opérateur <<."""
        return open(self.file, "a").write(shift)  # On ouvre le fichier en mode append.

Ce qui s'utiliserait comme ça :

>>> File("file.txt") << "Hello world"
11
>>> open("file.txt").read()
'Hello world'

Toutefois, cette solution n'est pas parfaite et nécessite d'inverser l'ordre de l'opérateur et des opérandes.

Elle offre tout de même une API élégante pour manipuler le contenu de fichiers facilement.