Table of Contents
Mise à jour des fonctionnalités de base en Python
Introduction
La transition de Python 2.x vers Python 3.x représente l’un des changements les plus significatifs dans l’histoire du langage Python. Depuis la fin du support officiel de Python 2 en janvier 2020, la migration vers Python 3 est devenue une nécessité absolue pour tous les développeurs et les organisations.
Les développeurs qui travaillent avec Python 2.x sont souvent confrontés à des problèmes lorsqu’ils passent à Python 3.x. De nombreuses fonctionnalités ont changé ou ont été supprimées pour améliorer la sécurité, la cohérence et les performances globales. Ces modifications, bien que parfois déroutantes au premier abord, rendent le code plus propre, plus prévisible et plus efficace.
Dans cet article, nous allons explorer en profondeur les mises à jour les plus importantes qui peuvent vous aider à passer plus facilement à Python 3.x. Nous couvrirons les changements concernant les imports relatifs, la fonction map(), l’arrondi des nombres, la gestion des fichiers, et bien d’autres aspects essentiels.
Référencement des classes dans un package
Lorsque vous avez plusieurs packages au sein d’un projet, il peut être difficile de référencer les classes et les fonctions qui se trouvent dans le package parent. Pour résoudre ce problème, vous pouvez utiliser le symbole .. pour faire référence aux objets du package parent.
Par exemple, si vous avez un projet avec la structure suivante :
square/
__init__.py
square.py
triangle/
__init__.py
triangle.py
util.py
Vous pouvez utiliser le code suivant dans square.py pour faire référence à la classe Util qui se trouve dans util.py :
from .. import util
Il est également possible d’utiliser l’importation globale avec * pour importer toutes les classes et fonctions du package parent :
from ..util import *
Cependant, il est généralement recommandé de faire des imports spécifiques pour éviter les conflits de nommage.
Voici un exemple plus complet illustrant les imports relatifs dans un projet structuré :
# Structure du projet
# myproject/
# __init__.py
# main.py
# utils/
# __init__.py
# helpers.py
# models/
# __init__.py
# user.py
# Dans models/user.py, pour importer depuis utils
from ..utils.helpers import format_date, validate_email
# Import absolu (recommandé pour plus de clarté)
from myproject.utils.helpers import format_date
Fonction map()
La fonction map() est une fonction intégrée qui permet d’appliquer une fonction à chaque élément d’une séquence. Cependant, ses comportements ont changé entre Python 2.x et Python 3.x.
En Python 2.x, la fonction map() retourne une liste. Par exemple :
>>> map(str, [1, 2, 3, 4, 5])
['1', '2', '3', '4', '5']
Cependant, en Python 3.x, la fonction map() retourne un objet de type map, qui est un générateur. Par exemple :
>>> map(str, [1, 2, 3, 4, 5])
<map object at 0x...>
Pour convertir ce générateur en liste, vous devez l’appeler avec la méthode list() :
>>> list(map(str, [1, 2, 3, 4, 5]))
['1', '2', '3', '4', '5']
Ce changement s’applique également à filter() et zip() qui retournent maintenant des iterateurs :
# Python 3.x - filter() retourne un iterateur
>>> filter(lambda x: x > 2, [1, 2, 3, 4, 5])
<filter object at 0x...>
>>> list(filter(lambda x: x > 2, [1, 2, 3, 4, 5]))
[3, 4, 5]
# Python 3.x - zip() retourne un iterateur
>>> zip([1, 2, 3], ['a', 'b', 'c'])
<zip object at 0x...>
>>> list(zip([1, 2, 3], ['a', 'b', 'c']))
[(1, 'a'), (2, 'b'), (3, 'c')]
Arrondi des nombres
La fonction round() est utilisée pour arrondir les nombres. Cependant, son comportement a changé entre Python 2.x et Python 3.x.
En Python 2.x, la fonction round() arrondit les nombres en fonction de leur position par rapport à l’unité la plus proche. Par exemple :
>>> round(1.5)
2
>>> round(0.5)
1
>>> round(-0.5)
-1
Cependant, en Python 3.x, la fonction round() suit la stratégie de rondeur « mi à même » (half to even), qui arrondit les nombres en fonction de leur valeur absolue.
Par exemple :
>>> round(1.5)
2
>>> round(0.5)
0
>>> round(-0.5)
0
Cette stratégie est plus précise et réduise le total des erreurs de rondeur.
Lecture/écriture de fichiers
La lecture/écriture de fichiers a également été modifiée en Python 3.x.
En Python 2.x, la fonction open() crée un objet de type file, qui peut être utilisé pour lire ou écrire des données. Par exemple :
>>> f = open('data.txt', 'r')
Cependant, en Python 3.x, la fonction open() crée un objet de type io.TextIOWrapper, qui est une classe dérivée de l’objet io.IOBase.
Par exemple :
>>> with open('data.txt', 'r') as f:
... data = f.read()
Suppression du cmp()
La fonction cmp() a été supprimée en Python 3.x, car elle n’est plus nécessaire.
En Python 2.x, la fonction cmp() est utilisée pour comparer deux objets. Par exemple :
>>> cmp(1, 2)
-1
Cependant, en Python 3.x, il est préférable d’utiliser les méthodes de comparaison spécifiques (par exemple __lt__(), __le__(), etc.) pour comparer deux objets.
Constantes octales
Les constantes octales ont également été modifiées en Python 3.x.
En Python 2.x, une constante octale peut être définie avec un préfixe « 0o ». Par exemple :
>>> 0755
Cependant, en Python 3.x, il est préférable d’utiliser la notation de littéral numérique décimal (par exemple 0o755).
Résultat de l’écriture dans un objet file
Lorsque vous écrivez directement dans un objet file, le résultat a changé entre Python 2.x et Python 3.x.
En Python 2.x, la fonction write() retourne None. Par exemple :
>>> hi = sys.stdout.write('hello world\n')
Cependant, en Python 3.x, la fonction write() retourne le nombre de caractères écrits. Par exemple :
>>> char_count = sys.stdout.write('hello world ?\n')
14
Exécution du code
La fonction exec() a été modifiée en Python 3.x.
En Python 2.x, la fonction exec() est utilisée pour exécuter un bloc de code. Par exemple :
>>> exec 'print("hello world")'
Cependant, en Python 3.x, la fonction exec() est une fonction standard et doit etre utilisee avec des parentheses :
# Python 3.x - exec() avec parentheses obligatoires
>>> exec('print("hello world")')
hello world
# Execution avec un contexte local
>>> local_vars = {}
>>> exec('x = 10; y = 20; result = x + y', {}, local_vars)
>>> print(local_vars['result'])
30
Division entiere
Un autre changement important concerne la division. En Python 2.x, la division de deux entiers retourne un entier :
# Python 2.x
>>> 5 / 2
2
# Python 3.x - division vraie par defaut
>>> 5 / 2
2.5
# Python 3.x - division entiere explicite
>>> 5 // 2
2
Bonnes Pratiques
Voici les bonnes pratiques a suivre lors de la migration de Python 2 vers Python 3 :
1. Utilisez l’outil 2to3
Python fournit un outil automatise pour convertir le code Python 2 en Python 3 :
# Analyser un fichier sans le modifier
2to3 script.py
# Appliquer les modifications
2to3 -w script.py
# Convertir un repertoire entier
2to3 -w -n mon_projet/
2. Utilisez __future__ pour une transition progressive
# En haut de vos fichiers Python 2
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import
from __future__ import unicode_literals
# Cela permet d'utiliser la syntaxe Python 3 dans Python 2
print("Hello") # Fonctionne dans les deux versions
3. Preferez les imports absolus
# A eviter
from . import module
# Prefere pour plus de clarte
from monpackage import module
4. Utilisez des context managers pour les fichiers
# Recommande
with open('fichier.txt', 'r', encoding='utf-8') as f:
contenu = f.read()
Pieges Courants
Voici les pieges les plus frequents lors de la migration :
1. Oublier de convertir map/filter/zip en liste
# Piege : le resultat n'est pas une liste
resultat = map(str, [1, 2, 3])
print(resultat[0]) # TypeError en Python 3!
# Solution
resultat = list(map(str, [1, 2, 3]))
print(resultat[0]) # '1'
2. Confusion entre bytes et str
# Python 3 distingue clairement bytes et str
texte = "Bonjour" # str (unicode)
donnees = b"Bonjour" # bytes
# Conversion necessaire
texte_encode = texte.encode('utf-8') # str -> bytes
donnees_decode = donnees.decode('utf-8') # bytes -> str
3. print sans parentheses
# Python 2 (ne fonctionne plus)
print "Hello"
# Python 3 (obligatoire)
print("Hello")
4. Comparaison de types differents
# Python 2 permettait ceci
>>> None < 3
True
# Python 3 leve une erreur
>>> None < 3
TypeError: '<' not supported between instances of 'NoneType' and 'int'
5. Dictionnaires non ordonnes
# En Python 3.7+, les dictionnaires preservent l'ordre d'insertion
# Mais ne vous y fiez pas si vous devez supporter Python 3.6 ou moins
from collections import OrderedDict
mon_dict = OrderedDict([('a', 1), ('b', 2)])
Conclusion
La migration de Python 2 vers Python 3 est une etape cruciale pour maintenir un code moderne, securise et performant. Les principaux changements a retenir sont :
- Les fonctions
map(),filter()etzip()retournent des iterateurs - L’arrondi utilise la strategie “banker’s rounding” (mi a pair)
- La division retourne un float par defaut
printest une fonction, pas une instruction- Les imports relatifs necessitent une syntaxe explicite
- La distinction entre
stretbytesest stricte
En suivant les bonnes pratiques decrites dans cet article et en utilisant les outils comme 2to3 et le module __future__, vous pouvez effectuer une migration progressive et sans douleur.
Prochaines etapes
- Migrer vos projets existants vers Python 3.x en utilisant
2to3 - Tester exhaustivement votre code apres migration
- Explorer les nouvelles fonctionnalites de Python 3 : f-strings, type hints, async/await
- Mettre a jour vos dependances vers des versions compatibles Python 3
- Configurer votre CI/CD pour tester uniquement sur Python 3
In-Article Ad
Dev Mode
Tags
Mahmoud DEVO
Senior Full-Stack Developer
I'm a passionate full-stack developer with 10+ years of experience building scalable web applications. I write about Vue.js, Node.js, PostgreSQL, and modern DevOps practices.
Enjoyed this article?
Subscribe to get more tech content delivered to your inbox.
Related Articles
La fonction map() en Python : guide complet avec exemples pratiques
Maitrisez la fonction map() en Python : utilisation de base, mapping de plusieurs iterables, differences Python 2.x vs 3.x et bonnes pratiques fonctionnelles.
Gestion des Fichiers en Python : Lecture, Ecriture et Manipulation de Repertoires
Guide complet pour gerer les fichiers en Python : lecture, ecriture, copie et manipulation de repertoires avec os, pathlib et shutil.
Recherche de valeurs dans les listes, tuples et dictionnaires Python
Apprenez a rechercher des elements dans les sequences Python : methode index(), mot-cle in, recherche dans les dictionnaires et algorithme bisect pour listes triees.