Maison  >  Article  >  développement back-end  >  bugs Python auxquels chaque développeur est encore confronté et comment les corriger)

bugs Python auxquels chaque développeur est encore confronté et comment les corriger)

WBOY
WBOYoriginal
2024-08-31 06:00:36479parcourir

ython bugs that every developer is still facing in and how to fix them)

Écrit par Rupesh Sharma AKA @hackyrupesh

Python, avec sa simplicité et sa beauté, est l'un des langages de programmation les plus populaires au monde. Cependant, même en 2024, certaines failles continuent de gêner les développeurs. Ces problèmes ne sont pas toujours dus à des faiblesses de Python, mais plutôt à sa conception, à son comportement ou à des idées fausses courantes qui entraînent des résultats imprévus. Dans cet article de blog, nous examinerons les 5 principaux problèmes Python que chaque développeur rencontre encore en 2024, ainsi que leurs solutions.


1. Arguments par défaut mutables : un piège silencieux

Le problème

L'un des bugs Python les plus tristement célèbres est l'argument par défaut mutable. Lorsqu'un objet mutable (comme une liste ou un dictionnaire) est utilisé comme argument par défaut dans une fonction, Python n'évalue cet argument par défaut qu'une seule fois lorsque la fonction est définie, et non à chaque fois que la fonction est appelée. Cela conduit à un comportement inattendu lorsque la fonction modifie l'objet.

Exemple

def append_to_list(value, my_list=[]):
    my_list.append(value)
    return my_list

print(append_to_list(1))  # Outputs: [1]
print(append_to_list(2))  # Outputs: [1, 2] - Unexpected!
print(append_to_list(3))  # Outputs: [1, 2, 3] - Even more unexpected!

La solution

Pour éviter cela, utilisez Aucun comme argument par défaut et créez une nouvelle liste à l'intérieur de la fonction si nécessaire.

def append_to_list(value, my_list=None):
    if my_list is None:
        my_list = []
    my_list.append(value)
    return my_list

print(append_to_list(1))  # Outputs: [1]
print(append_to_list(2))  # Outputs: [2]
print(append_to_list(3))  # Outputs: [3]

Références

  • L'argument par défaut de Python est un piège

2. L'erreur de clé insaisissable dans les dictionnaires

Le problème

KeyError se produit lorsque vous essayez d'accéder à une clé de dictionnaire qui n'existe pas. Cela peut être particulièrement délicat lorsque vous travaillez avec des dictionnaires imbriqués ou lorsque vous traitez des données dont la structure n'est pas garantie.

Exemple

data = {'name': 'Alice'}
print(data['age'])  # Raises KeyError: 'age'

La solution

Pour éviter KeyError, utilisez la méthode get(), qui renvoie None (ou une valeur par défaut spécifiée) si la clé n'est pas trouvée.

print(data.get('age'))  # Outputs: None
print(data.get('age', 'Unknown'))  # Outputs: Unknown

Pour les dictionnaires imbriqués, pensez à utiliser le defaultdict du module de collections ou des bibliothèques comme dotmap ou pydash.

from collections import defaultdict

nested_data = defaultdict(lambda: 'Unknown')
nested_data['name'] = 'Alice'
print(nested_data['age'])  # Outputs: Unknown

Références

  • Python KeyError et comment le gérer

3. Erreurs silencieuses avec tentative d'utilisation excessive

Le problème

Une utilisation excessive ou abusive des blocs try-sauf peut conduire à des erreurs silencieuses, où les exceptions sont interceptées mais mal gérées. Cela peut rendre les bogues difficiles à détecter et à déboguer.

Exemple

try:
    result = 1 / 0
except:
    pass  # Silently ignores the error
print("Continuing execution...")

Dans l'exemple ci-dessus, la ZeroDivisionError est détectée et ignorée, mais cela peut masquer le problème sous-jacent.

La solution

Spécifiez toujours le type d'exception que vous interceptez et gérez-le de manière appropriée. La journalisation de l'erreur peut également aider à localiser les problèmes.

try:
    result = 1 / 0
except ZeroDivisionError as e:
    print(f"Error: {e}")
print("Continuing execution...")

Pour une gestion plus large des exceptions, vous pouvez utiliser la journalisation au lieu de pass :

import logging

try:
    result = 1 / 0
except Exception as e:
    logging.error(f"Unexpected error: {e}")

Références

  • Les meilleures pratiques d'essai de Python

4. Division entière : le piège de la troncature

Le problème

Avant Python 3, la division de deux entiers effectuait une division au sol par défaut, tronquant le résultat en un entier. Bien que Python 3 ait résolu ce problème avec une véritable division (/), certains développeurs sont toujours confrontés à des problèmes lorsqu'ils utilisent involontairement la division au sol (//).

Exemple

print(5 / 2)  # Outputs: 2.5 in Python 3, but would be 2 in Python 2
print(5 // 2)  # Outputs: 2

La solution

Utilisez toujours / pour la division, sauf si vous avez spécifiquement besoin d'une division au sol. Soyez prudent lorsque vous portez du code de Python 2 vers Python 3.

print(5 / 2)  # Outputs: 2.5
print(5 // 2)  # Outputs: 2

Pour un code clair et prévisible, pensez à utiliser decimal.Decimal pour des opérations arithmétiques plus précises, en particulier dans les calculs financiers.

from decimal import Decimal

print(Decimal('5') / Decimal('2'))  # Outputs: 2.5

Références

  • Division Python : /vs //

5. Fuites de mémoire avec références circulaires

Le problème

Le garbage collector de Python gère l'essentiel de la gestion de la mémoire, mais les références circulaires peuvent provoquer des fuites de mémoire si elles ne sont pas gérées correctement. Lorsque deux objets ou plus se référencent mutuellement, ils peuvent ne jamais être récupérés, ce qui entraîne une utilisation accrue de la mémoire.

Exemple

class Node:
    def __init__(self, value):
        self.value = value
        self.next = None

node1 = Node(1)
node2 = Node(2)
node1.next = node2
node2.next = node1  # Circular reference

del node1
del node2  # Memory not freed due to circular reference

La solution

Pour éviter les références circulaires, pensez à utiliser des références faibles via le module lowref, qui permet de récupérer les références lorsqu'aucune référence forte n'existe.

import weakref

class Node:
    def __init__(self, value):
        self.value = value
        self.next = None

node1 = Node(1)
node2 = Node(2)
node1.next = weakref.ref(node2)
node2.next = weakref.ref(node1)  # No circular reference now

Vous pouvez également interrompre manuellement le cycle en définissant les références sur Aucune avant de supprimer les objets.

node1.next = None
node2.next = None
del node1
del node2  # Memory is freed

References

  • Python Memory Management and Garbage Collection

Conclusion

Even in 2024, Python developers continue to encounter these common bugs. While the language has evolved and improved over the years, these issues are often tied to fundamental aspects of how Python works. By understanding these pitfalls and applying the appropriate solutions, you can write more robust, error-free code. Happy coding!


Written by Rupesh Sharma AKA @hackyrupesh

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn