Les codes fantastiques : bouturage

Magazine
Marque
GNU/Linux Magazine
Numéro
265
Mois de parution
septembre 2023
Spécialité(s)


Résumé

Nouvel épisode des codes fantastiques avec une histoire de clonage d’arbres en Python.


Body

Pour créer un clone d’un objet en Python, la méthode standard est d’utiliser la fonction deepcopy disponible dans le module standard copy. Dans le cas qui m’intéresse, je dois cloner un objet issu de la désérialisation d’un objet au format JSON. Cela nous donne deux propriétés : l’objet est un arbre (il n’y a pas dans la structure de l’objet deux références sur le même objet), et il ne contient que des types de base (bool, int, str, float, dict, list). Essayons de voir si l’on peut exploiter ces propriétés pour faire une copie en profondeur rapide. Commençons par un petit exemple de référence :

>>> obj = { 1 : 1., True : ‘hello’, ‘pof’ : [‘a’, ‘b’, ‘c’]}
>>> %timeit deepcopy(obj)
2.06 µs ± 13.6 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

On observe par ailleurs que la signature de copy.deepcopy est la suivante :

deepcopy(x, memo=None, _nil=[])

Le paramètre memo est un objet de type dictionnaire qui permet de stocker les correspondances entre objet de référence et clone, et d’ainsi gérer les références multiples. Dans notre cas, on peut éviter les interactions avec cet objet (pas de références multiples dans notre arbre), cela devrait nous éviter quelques indexations de tableau.

On peut aussi inspecter le code de deepcopy dans la bibliothèque Python :

>>> import inspect
>>> print(inspect.getsource(deepcopy))
[...]
    copier = _deepcopy_dispatch.get(cls)
    if copier is not None:
        y = copier(x, memo)
    else:
        if issubclass(cls, type):
            y = _deepcopy_atomic(x, memo)
        else:
            copier = getattr(x, "__deepcopy__", None)
            if copier is not None:
                y = copier(memo)
            else:
                reductor = dispatch_table.get(cls)
[...]

La mécanique est assez générique : elle gère la méthode magique __deepcopy__, effectue un appel rapide aux fonctions copy._deepcopy_list ou copy._deepcopy_dict à travers le dictionnaire _deepcopy_dispatch... On peut s’inspirer de cette stratégie pour une implémentation simple et efficace (car utilisant peu d’appels de fonctions et faisant quelques hypothèses sur les types rencontrés) pour notre objet simplifié :

>>> def deepcopy_tree(obj):
...   if isinstance(obj, list): return [deepcopy_tree(x) for x in obj]
...   elif isinstance(obj, dict): return {k: deepcopy_tree(v) for k, v in obj.items()}
...   else: return obj # int, str etc are immutable
>>> %timeit deepcopy_tree(obj)
705 ns ± 2.47 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

On notera qu’on ne clone pas les clés de dictionnaires : elles sont immuables par définition.

Pour pousser un peu plus loin l’intégration, on pourrait même encapsuler notre arbre dans une classe avec une méthode __deepcopy__ :-).



Article rédigé par

Par le(s) même(s) auteur(s)

Introduction au dossier : Sécurisez vos codes

Magazine
Marque
MISC
HS n°
Numéro
30
Mois de parution
octobre 2024
Spécialité(s)
Résumé

La sécurité des codes… En voilà un sujet fourre-tout où n’importe quel article de MISC trouverait sa place ! Pour apporter une petite touche personnelle, et faire un petit clin d’œil à mon héritage familial, j’ai choisi de prendre un axe historique pour la constitution de ce dossier.

Garder ses parties privées

Magazine
Marque
MISC
HS n°
Numéro
30
Mois de parution
octobre 2024
Spécialité(s)
Résumé

Il y a 19 ans, Ulrich Drepper, alors développeur chez Red Hat et un des contributeurs principaux de la glibc, ajoutait au changelog de la glibc la ligne suivante : sysdeps/i386/bsd-_setjmp.S: Use PTR_MANGLE for PC if defined, inaugurant ainsi l’arrivée de la protection des pointeurs de fonction stockés dans des structures internes à la glibc.

Des soucis à la chaîne

Magazine
Marque
MISC
HS n°
Numéro
30
Mois de parution
octobre 2024
Spécialité(s)
Résumé

L’histoire, ou plutôt l’Histoire, est une coquine. Et quand Dennis Ritchie et Ken Thompson inventent le langage C en 1972, ils prennent une décision anodine, une micro-optimisation qui fait gagner quelques octets, mais qui aura un impact important sur la sécurité de nombreux systèmes : en C, les chaînes de caractères sont terminées par un octet positionné à zéro.

Les derniers articles Premiums

Les derniers articles Premium

Sécurisez vos applications web : comment Symfony vous protège des menaces courantes

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Les frameworks tels que Symfony ont bouleversé le développement web en apportant une structure solide et des outils performants. Malgré ces qualités, nous pouvons découvrir d’innombrables vulnérabilités. Cet article met le doigt sur les failles de sécurité les plus fréquentes qui affectent même les environnements les plus robustes. De l’injection de requêtes à distance à l’exécution de scripts malveillants, découvrez comment ces failles peuvent mettre en péril vos applications et, surtout, comment vous en prémunir.

Bash des temps modernes

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Les scripts Shell, et Bash spécifiquement, demeurent un standard, de facto, de notre industrie. Ils forment un composant primordial de toute distribution Linux, mais c’est aussi un outil de prédilection pour implémenter de nombreuses tâches d’automatisation, en particulier dans le « Cloud », par eux-mêmes ou conjointement à des solutions telles que Ansible. Pour toutes ces raisons et bien d’autres encore, savoir les concevoir de manière robuste et idempotente est crucial.

Présentation de Kafka Connect

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Un cluster Apache Kafka est déjà, à lui seul, une puissante infrastructure pour faire de l’event streaming… Et si nous pouvions, d’un coup de baguette magique, lui permettre de consommer des informations issues de systèmes de données plus traditionnels, tels que les bases de données ? C’est là qu’intervient Kafka Connect, un autre composant de l’écosystème du projet.

Le combo gagnant de la virtualisation : QEMU et KVM

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

C’est un fait : la virtualisation est partout ! Que ce soit pour la flexibilité des systèmes ou bien leur sécurité, l’adoption de la virtualisation augmente dans toutes les organisations depuis des années. Dans cet article, nous allons nous focaliser sur deux technologies : QEMU et KVM. En combinant les deux, il est possible de créer des environnements de virtualisation très robustes.

Les listes de lecture

9 article(s) - ajoutée le 01/07/2020
Vous désirez apprendre le langage Python, mais ne savez pas trop par où commencer ? Cette liste de lecture vous permettra de faire vos premiers pas en découvrant l'écosystème de Python et en écrivant de petits scripts.
11 article(s) - ajoutée le 01/07/2020
La base de tout programme effectuant une tâche un tant soit peu complexe est un algorithme, une méthode permettant de manipuler des données pour obtenir un résultat attendu. Dans cette liste, vous pourrez découvrir quelques spécimens d'algorithmes.
10 article(s) - ajoutée le 01/07/2020
À quoi bon se targuer de posséder des pétaoctets de données si l'on est incapable d'analyser ces dernières ? Cette liste vous aidera à "faire parler" vos données.
Voir les 65 listes de lecture

Abonnez-vous maintenant

et profitez de tous les contenus en illimité

Je découvre les offres

Déjà abonné ? Connectez-vous