153 votes

Est-ce que c'est pythonique d'importer à l'intérieur des fonctions ?

PEP 8 dit :

  • Les importations sont toujours placées en tête de fichier, juste après les modules. et la documentation, et avant les globales et constantes du module.

Il m'arrive de violer le PEP 8. Parfois, j'importe des éléments à l'intérieur de fonctions. En règle générale, je le fais si une importation n'est utilisée qu'au sein d'une seule fonction.

Des avis ?

EDIT (la raison pour laquelle je pense que l'importation dans les fonctions peut être une bonne idée) :

Principale raison : cela peut rendre le code plus clair.

  • Lorsque je regarde le code d'une fonction, je peux me demander : "Qu'est-ce que la fonction/classe xxx ?" (xxx étant utilisé à l'intérieur de la fonction). Si tous mes imports se trouvent en haut du module, je dois aller voir là pour déterminer ce qu'est xxx. Le problème se pose davantage lorsque l'on utilise from m import xxx . Voir m.xxx dans la fonction m'en dit probablement plus. En fonction de ce que m est : S'agit-il d'un module/paquet de premier niveau bien connu ( import m ) ? Ou s'agit-il d'un sous-module/paquet ( from a.b.c import m ) ?
  • Dans certains cas, le fait de disposer de cette information supplémentaire ("Qu'est-ce que xxx ?") à proximité de l'endroit où xxx est utilisé peut faciliter la compréhension de la fonction.

113voto

Peter Ericson Points 483

A long terme, je pense que vous apprécierez d'avoir la plupart de vos importations en haut du fichier, de cette façon vous pourrez voir d'un coup d'œil à quel point votre module est compliqué par ce qu'il a besoin d'importer.

Si j'ajoute un nouveau code à un fichier existant, j'effectue généralement l'importation là où c'est nécessaire, puis, si le code reste, je rends les choses plus permanentes en déplaçant la ligne d'importation au début du fichier.

Un autre point, je préfère obtenir un ImportError avant que le code ne soit exécuté - comme un contrôle d'intégrité, c'est donc une autre raison d'importer en haut de l'échelle.

J'utilise pyChecker pour vérifier la présence de modules inutilisés.

57voto

Rick Copeland Points 5343

À deux reprises, j'ai enfreint le PEP 8 à cet égard :

  • Importations circulaires : le module A importe le module B, mais quelque chose dans le module B a besoin du module A (bien que ce soit souvent un signe que je dois remanier les modules pour éliminer la dépendance circulaire).
  • Insertion d'un point d'arrêt pdb : import pdb; pdb.set_trace() C'est pratique, car je ne veux pas mettre en place un système d'alerte. import pdb au début de chaque module que je pourrais vouloir déboguer, et il est facile de se rappeler de supprimer l'importation lorsque je supprime le point d'arrêt.

En dehors de ces deux cas, il est conseillé de tout placer en tête de page. Cela rend les dépendances plus claires.

23voto

S.Lott Points 207588

Voici les quatre cas d'utilisation des importations que nous utilisons

  1. import (et from x import y y import x as y ) au sommet

  2. Choix pour l'importation. En haut.

    import settings
    if setting.something:
        import this as foo
    else:
        import that as foo
  3. Importation conditionnelle. Utilisé avec les bibliothèques JSON, XML et autres. En haut de la page.

    try:
        import this as foo
    except ImportError:
        import that as foo
  4. Importation dynamique. Jusqu'à présent, nous n'avons qu'un seul exemple.

    import settings
    module_stuff = {}
    module= __import__( settings.some_module, module_stuff )
    x = module_stuff['x']

    Notez que cette importation dynamique n'apporte pas de code, mais des données complexes complexes écrites en Python. C'est un peu comme un morceau de données décapées sauf que nous l'avons décapé à la main.

    C'est aussi, plus ou moins, au sommet d'un module


Voici ce que nous faisons pour rendre le code plus clair :

  • Les modules doivent être courts.

  • Si tous mes imports se trouvent en haut du module, je dois aller voir là pour déterminer ce qu'est un nom. Si le module est court, c'est facile à faire.

  • Dans certains cas, le fait de disposer de ces informations supplémentaires à proximité de l'endroit où un nom est utilisé peut faciliter la compréhension de la fonction. Si le module est court, c'est facile à faire.

10voto

Jason Baker Points 56682

Une chose à garder à l'esprit : les importations inutiles peuvent entraîner des problèmes de performance. Par conséquent, s'il s'agit d'une fonction qui sera appelée fréquemment, il est préférable de placer l'importation en haut de la page. Bien entendu, cette fonction est Il s'agit d'une optimisation, donc s'il est vrai que l'importation à l'intérieur d'une fonction est plus claire que l'importation au début d'un fichier, cela l'emporte sur les performances dans la plupart des cas.

Si vous utilisez IronPython, on m'a dit qu'il était préférable d'importer à l'intérieur des fonctions (car la compilation du code en IronPython peut être lente). Ainsi, vous pourrez peut-être vous arranger avec l'importation à l'intérieur des fonctions. Mais à part cela, je dirais qu'il ne vaut pas la peine de se battre contre les conventions.

En règle générale, je procède ainsi lorsqu'une importation n'est utilisée que dans une seule fonction.

J'aimerais également souligner qu'il peut s'agir d'un problème d'entretien potentiel. Que se passe-t-il si vous ajoutez une fonction qui utilise un module qui n'était auparavant utilisé que par une seule fonction ? Allez-vous vous souvenir d'ajouter l'importation au début du fichier ? Ou bien allez-vous analyser chaque fonction pour y trouver des importations ?

À titre d'information, il existe des cas où il est judicieux d'importer à l'intérieur d'une fonction. Par exemple, si vous voulez définir la langue dans cx_Oracle, vous devez définir un NLS _ Variable d'environnement LANG avant il est importé. Ainsi, vous pouvez voir un code comme celui-ci :

import os

oracle = None

def InitializeOracle(lang):
    global oracle
    os.environ['NLS_LANG'] = lang
    import cx_Oracle
    oracle = cx_Oracle

6voto

Daniel Lew Points 39063

J'ai déjà enfreint cette règle pour des modules qui s'auto-testent. C'est-à-dire qu'ils sont normalement utilisés pour le support, mais je leur définis un main pour que si vous les exécutez seuls, vous puissiez tester leur fonctionnalité. Dans ce cas, j'importe parfois getopt y cmd juste en principal, parce que je veux qu'il soit clair pour quelqu'un qui lit le code que ces modules n'ont rien à voir avec le fonctionnement normal du module et qu'ils ne sont inclus que pour les tests.

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