web-dev-qa-db-fra.com

Importation de modules dans Python - meilleure pratique

Je suis nouveau dans Python car je veux étendre les compétences que j'ai apprises en utilisant R. Dans R, j'ai tendance à charger un tas de bibliothèques, entraînant parfois des conflits de nom de fonction.

Quelle est la meilleure pratique en Python. J'ai vu des variations spécifiques que je ne vois pas de différence entre

import pandas, from pandas import *, et from pandas import DataFrame

Quelles sont les différences entre les deux premiers et dois-je simplement importer ce dont j'ai besoin. De plus, quelles seraient les pires conséquences pour quelqu'un qui crée de petits programmes pour traiter des données et calculer des statistiques simples.

[~ # ~] mise à jour [~ # ~]

J'ai trouvé cela excellent guide . Ça explique tout.

57
John

import pandas importe le module pandas sous l'espace de noms pandas, vous devrez donc appeler des objets dans pandas en utilisant pandas.foo.

from pandas import * importe tous les objets du module pandas dans votre espace de noms actuel, vous devez donc appeler les objets dans pandas en utilisant uniquement foo. Conserver dans attention, cela pourrait avoir des conséquences inattendues s'il y a des conflits de noms entre votre espace de noms actuel et l'espace de noms pandas.

from pandas import DataFrame est le même que ci-dessus, mais importe uniquement DataFrame (au lieu de tout) dans votre espace de noms actuel.

À mon avis, la première est généralement la meilleure pratique, car elle maintient les différents modules bien compartimentés dans votre code.

43
Paul

Inconvénient de chaque formulaire

En lisant le code d'autres personnes (et ces personnes utilisent des styles d'importation très différents), j'ai remarqué les problèmes suivants avec chacun des styles:

import modulewithaverylongname encombrera le code plus bas avec le nom long du module (par exemple concurrent.futures ou Django.contrib.auth.backends) et diminuer la lisibilité à ces endroits.

from module import * ne me donne aucune chance de voir syntaxiquement que, par exemple, classA et classB proviennent du même module et ont beaucoup à voir l'un avec l'autre . Cela rend la lecture du code difficile. (Le fait que les noms d'une telle importation puissent masquer les noms d'une importation antérieure est la moindre partie de ce problème.)

from module import classA, classB, functionC, constantD, functionE surcharge ma mémoire à court terme avec trop de noms que je dois mentalement attribuer à module afin de comprendre le code de manière cohérente.

import modulewithaverylongname as mwvln est parfois insuffisamment mnémonique pour moi.

Un compromis adapté

Sur la base des observations ci-dessus, j'ai développé le style suivant dans mon propre code:

import module est le style préféré si le nom du module est court comme par exemple la plupart des packages de la bibliothèque standard. C'est aussi le style préféré si j'ai besoin d'utiliser des noms du module à seulement deux ou trois endroits dans mon propre module; la clarté l'emporte alors sur la brièveté ( "La lisibilité compte" ).

import longername as ln est le style préféré dans presque tous les autres cas. Par exemple, je pourrais import Django.contrib.auth.backends as dj_abe. Par définition du critère 1 ci-dessus, l'abréviation sera utilisée fréquemment et est donc suffisamment facile à mémoriser.

Seuls ces deux styles sont entièrement Pythonic selon la règle "Explicit vaut mieux qu'implicite." .

from module import xx se produit toujours parfois dans mon code. Je l'utilise dans les cas où même le format as semble exagéré, l'exemple le plus célèbre étant from datetime import datetime.

29
Lutz Prechelt

En général, il vaut mieux faire des importations explicites. Un péché:

import pandas
frame = pandas.DataFrame()

Ou:

from pandas import DataFrame
frame = DataFrame()

Une autre option en Python, lorsque vous avez des noms en conflit, est d'importer x en tant que y:

from pandas import DataFrame as PDataFrame
from bears import DataFrame as BDataFrame
frame1 = PDataFrame()
frame2 = BDataFrame()
23
Carles Barrobés

Voici quelques recommandations de PEP8 Style Guide.

  1. Les importations doivent généralement être effectuées sur des lignes distinctes , par exemple:

    Yes: import os
         import sys
    
    No:  import sys, os
    

    mais ça va

    from subprocess import Popen, PIPE
    
  2. Les importations sont toujours placées en haut du fichier, juste après les commentaires et les docstrings du module, et avant les globales et les constantes du module.

    • Les importations doivent être regroupées dans l'ordre suivant:
      1. importations de bibliothèques standard
      2. importations de tiers liées
      3. importations spécifiques à une application/bibliothèque locale
    • Vous devez mettre une ligne vierge entre chaque groupe d'importations.
  3. Les importations absolues sont recommandées
    Ils sont plus lisibles et facilitent le débogage en donnant de meilleurs messages d'erreur au cas où vous gâcheriez le système d'importation.

    import mypkg.sibling
    from mypkg import sibling
    from mypkg.sibling import example
    

    ou importations relatives explicites

    from . import sibling
    from .sibling import example
    
  4. Les importations relatives implicites ne doivent jamais être utilisées et sont supprimées dans Python 3.

    No:  from ..grand_parent_package import uncle_package
    
  5. Importations génériques (from <module> import *) doit être évité , car ils ne permettent pas de savoir quels noms sont présents dans l'espace de noms, ce qui confond les lecteurs et de nombreux outils automatisés.


Quelques recommandations sur lazy imports de conseils de performances de vitesse python.

Frais généraux de déclaration d'importation

les instructions d'importation peuvent être exécutées à peu près n'importe où. Il est souvent utile de les placer dans des fonctions pour restreindre leur visibilité et/ou réduire le temps de démarrage initial. Bien que l'interpréteur de Python soit optimisé pour ne pas importer le même module plusieurs fois, l'exécution répétée d'une instruction d'importation peut sérieusement affecter les performances dans certaines circonstances.

ce qui suit est un scénario expliqué à la page,

>>> def doit1():
... import string
... string.lower('Python')
...
>>> import string
>>> def doit2():
... string.lower('Python')
...
>>> import timeit
>>> t = timeit.Timer(setup='from __main__ import doit1', stmt='doit1()')
>>> t.timeit()
11.479144930839539
>>> t = timeit.Timer(setup='from __main__ import doit2', stmt='doit2()')
>>> t.timeit()
4.6661689281463623
14
from A import B

est essentiellement égal à la suite de trois déclarations

import A
B = A.B
del A

Voilà, c'est tout.

9
XuZhangning

Ils conviennent tous dans des contextes différents (c'est pourquoi ils sont tous disponibles). Il n'y a pas de principe directeur profond, autre que les déclarations génériques de maternité concernant la clarté, la maintenabilité et la simplicité. Quelques exemples de mon propre code:

  1. import sys, os, re, itertools Évite les collisions de noms et fournit un moyen très succinct d'importer un tas de modules standard.
  2. from math import * Me permet d'écrire sin(x) au lieu de math.sin(x) en code mathématique. Cela devient un peu risqué lorsque j'importe également numpy, ce qui double sur certains d'entre eux, mais cela ne me préoccupe pas trop, car ce sont généralement les mêmes fonctions de toute façon. De plus, j'ai tendance à suivre la documentation numpy - import numpy as np - qui évite complètement le problème.
  3. Je préfère from PIL import Image, ImageDraw Simplement parce que c'est ainsi que la documentation PIL présente ses exemples.
2
Marcelo Cantos