61 votes

Organiser les classes Python en modules et/ou en paquets

J'aime la convention Java qui consiste à n'avoir qu'une seule classe publique par fichier, même s'il y a parfois de bonnes raisons de mettre plus d'une classe publique dans un seul fichier. Dans mon cas, j'ai des implémentations alternatives de la même interface. Mais si je les plaçais dans des fichiers séparés, j'aurais des noms redondants dans les déclarations d'importation (ou des noms de modules trompeurs) :

import someConverter.SomeConverter

alors que someConverter serait le nom du fichier (et du module) et SomeConverter le nom de la classe. Cela me semble assez inélégant. Mettre toutes les classes alternatives dans un seul fichier conduirait à une déclaration d'importation plus significative :

import converters.SomeConverter

Mais je crains que les fichiers deviennent assez volumineux si je place toutes les classes connexes dans un seul fichier de module. Quelle est la meilleure pratique Python dans ce cas ? Une classe par fichier est-elle inhabituelle ?

9 votes

Lorsque vous aurez à gérer un projet composé de 10 000 classes, vous serez heureux de pouvoir trouver une classe (publique) par son nom de fichier (et de paquetage) au lieu de devoir chercher dans le contenu de tous les fichiers. C'est probablement la raison pour laquelle Java impose qu'il n'y ait qu'une seule classe publique par fichier et que le nom du fichier soit le nom de la classe.

62voto

Zach Points 4886

C'est en grande partie une question de préférence personnelle. En utilisant les modules python, vous avez la possibilité de garder chaque classe dans un fichier séparé tout en permettant à import converters.SomeConverter (ou from converters import SomeConverter )

La structure de vos fichiers pourrait ressembler à ceci :

* converters
     - __init__.py
     - baseconverter.py
     - someconverter.py
     - otherconverter.py

et ensuite dans votre __init__.py fichier :

from baseconverter import BaseConverter
from otherconverter import OtherConverter

51voto

Spundun Points 1634

La solution de Zach ne fonctionne pas avec Python 3. Voici une solution corrigée.

C'est en grande partie une question de préférence personnelle. En utilisant les modules python, vous avez la possibilité de garder chaque classe dans un fichier séparé tout en permettant à import converters.SomeConverter (ou from converters import SomeConverter )

La structure de vos fichiers pourrait ressembler à ceci :

* converters
     - __init__.py
     - baseconverter.py
     - someconverter.py
     - otherconverter.py

et ensuite dans votre __init__.py fichier :

from converters.baseconverter import BaseConverter
from converters.otherconverter import OtherConverter

8 votes

Pourquoi pas simplement "from .baseconverter import BaseConverter" ?

0 votes

Désolé pour le suivi tardif, j'ai été déconnecté de Python ces derniers temps. Si quelqu'un peut vérifier la solution de Michael ci-dessus, n'hésitez pas à modifier ma réponse et à l'ajouter comme alternative. (Ne changez pas ma réponse originale car je pense que c'est une question de préférence quant à celle qui est la plus lisible, alors donnons aux utilisateurs les deux options).

8 votes

La réponse de Michael fonctionne, mais PEP 8 décourage les importations relatives. stackoverflow.com/questions/4209641/

5voto

Ehtesham Siddiqui Points 253

Les solutions ci-dessus sont bonnes, mais le problème de l'importation de modules en __init__.py est que cela va causer tous les modules doivent être chargés deux fois (inefficace) . Essayez d'ajouter une instruction print à la fin de otherconverter.py et exécuter otherconverter.py . (Vous verrez que l'instruction print est exécutée deux fois).

Je préfère ce qui suit. Utilisez un autre paquet avec le nom "_converter" et définissez tout là-bas. Et ensuite votre "converters.py" devient l'interface pour accéder à tous les membres publics

* _converters
     - __init__.py
     - baseconverter.py
     - someconverter.py
     - otherconverter.py

*  converters.py

converters.py est

from _converters.someconverter import SomeConverter
from _converters.otherconverter import OtherConverter
...
...
...
converters = [SomeConverter, OtherConverter, ...]

Et comme les solutions précédentes l'ont mentionné, c'est un choix personnel. Quelques pratiques consistent à définir un module "interace.py" au sein du paquetage et à y importer tous les membres publics. Si vous avez beaucoup de modules à charger, vous devriez choisir l'efficacité plutôt que l'esthétique.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X