Python: Pourquoi 'de <module> import *' - elle être interdite?
Si vous avez
from <module> import *
dans le milieu de votre programme (ou un module), vous obtiendrez l'attention:
/tmp/foo:100: SyntaxWarning: import * only allowed at module level
Je comprends pourquoi import *
est déconseillé en général (espace de noms de l'invisibilité),
mais il existe de nombreuses situations où il s'avérerait pratique, surtout lorsqu'
le code n'est pas partagé avec quiconque.
Donc, quelqu'un peut-il expliquer précisément en détail pourquoi from <module> import *
devrait
être interdit dans tous les cas possibles?
- qui IDE que vous utilisez qui déclenche avertissement?
- J'ai écrit un post de blog qui explique pourquoi il doit être interdit à la non-étendue globale: lesinskis.com/TIL_python_imports.html
Vous devez vous connecter pour publier un commentaire.
Je crois que par "dans le milieu de votre programme" vous parlez d'une importation à l'intérieur de une définition de fonction:
Ce n'est pas permis parce qu'il ferait en optimisant le corps de la fonction trop dur. Le Python de la mise en œuvre veut savoir tous les noms de fonction les variables locales de quand il octet-compile une fonction, de sorte qu'il peut optimiser les références à des variables dans les opérations sur le (Disponible) de la machine virtuelle de l'opérande de la pile, ou au moins à une variable locale de la fente d'opérations plutôt que les recherches dans l'espace de noms. Si vous pouviez faire un dump de la totalité du contenu d'un module en fonction de l'espace de noms local, alors le compilateur aurait à assumer que tout nom de la fonction peut éventuellement se référer à un module global, parce que la liste des noms portés par la
from module import *
n'est connue qu'à l'exécution.Mettre
from module import *
entre haut niveau des déclarations de style pauvres, mais il est permis:EDITION avril 2013: Tout en regardant vers quelque chose d'autre, j'ai découvert que cette restriction a été introduite en Python 2.1, comme une conséquence de la "Imbriqués les Étendues de" fonctionnalité (PEP 227). En citant le lien:
Cela clarifie le Python 3.x vs 2.x le comportement décrit dans les commentaires. Il est toujours contraire à la spécification du langage, mais Disponible 2.1 à 2.7 seulement question d'une erreur pour
from module import *
dans une fonction si cela peut nuire à la capacité du compilateur de savoir si une variable lie localement ou dans un contenant de portée. En 3.x, il a été promu à un inconditionnel d'erreur.FILS DE EDIT: ... et apparemment flashk l'a souligné il y a des années dans une autre réponse, citant le même paragraphe de la rubrique "Quoi de neuf en Python 2.1" encore. Y'all aller upvote que maintenant.
import *
est autorisé dans un corps de la fonction (avec un avertissement) si elle n'est pas, ou n'ont pas, le tout imbriqué bloc; (2) Si Python doc a dit qu'il n'est pas permis, sauf à haut niveau d'un module, il n'est jamais forcée (c'est à dire, toujours possible); (3) Si l'octet compilateur peut exécuter le module afin qu'il sache que toutes les variables et fonctions, ce ne sera pas un problème pour l'optimisation; (4) Montrez-moi un exemple de ce qui est devenu de mal avec le imbriquée portée, Python.x = 3
et une fonctiondef foo(): print x
, alors x est une variable libre de foo. Ce n'est pas un mot de fouine - voir docs.python.org/reference/executionmodel.html pour la définition. "Si une variable est utilisée dans un bloc de code, mais pas définie, elle est une variable libre."def f(): from module import *
" exemple.À tout niveau lexical,
from amodule import *
est un "semblait une bonne idée à l'époque de" la conception de la décision qui a été une véritable catastrophe dans la vraie vie, avec la possible exception de la pratique de l'exploration à la interactives interpréteur de commandes (même alors, je ne suis pas trop chaud sur elle --import module as m
les forces de deux caractères supplémentaires à utiliser les noms complets au lieu de cela [[juste unm.
préfixe]], et noms qualifiés sont toujours plus nette et plus flexible que barenames, pour ne pas mentionner la grande utilité dans exploratoire des situations interactives d'avoirm
disponibles pourhelp(m)
,reload(m)
, et ainsi de suite!).Ce caviardée de construire, il est très difficile, pour les pauvres, en lisant le code (souvent dans une tentative vouée à aider à déboguer) pour comprendre d'où mystérieusement apparaître les noms sont à venir à partir de -- impossible, si la construction est utilisé plus d'une fois sur un niveau lexical; mais même lorsqu'il est utilisé juste une fois, c'forces laborieuses re-lecture de l'ensemble du module à chaque fois, avant de se convaincre soi-même que, oui, ça caviardée barename doit venir du module.
Plus, le module auteurs ont l'habitude de ne pas aller à l'extrême difficulté nécessaires pour "soutenir" les horribles construire en question. Si quelque part dans votre code, vous avez, disons, une utilisation de
sys.argv
(et unimport sys
tout en haut de votre module, bien sûr), comment voulez-vous savoir quesys
est le module qu'il devrait être... ou d'autres complètement différents l'un (ou une non-module) provenant de la... import *
?! Multipliez cela par tous les noms qualifiés que vous utilisez, et la misère est le seul résultat final-que, et le mystérieux bugs nécessitant long, laborieux de débogage (généralement avec les réticents de l'aide de quelqu'un qui ne "get" Python...!-).Au sein d'une fonction, une façon d'ajouter et remplacer arbitraire des noms locaux serait encore pire. Comme au primaire, mais cruciale, l'optimisation, le Python compilateur recherche autour de la fonction du corps pour une cession ou d'une autre liaison déclarations sur chaque barename, et juge que "local" ces noms, il voit donc attribué (les autres doivent être globales ou built-ins). Avec un
import *
(comme avec unexec somestring
sans autorisation explicite et dicts utiliser que des espaces de noms), tout à coup, il devient un total mystère dont les noms sont locales, dont les noms sont mondial -- de sorte que les pauvres compilateur aurait du avoir recours à la plus lente possible stratégie pour chaque recherche de nom, à l'aide d'un dict pour les variables locales (au lieu de l'compact "vecteur" qu'il utilise normalement) et d'effectuer jusqu'à trois dict look-ups pour chaque barename référencé, plus et plus.Aller à n'importe quel Python interactif invite. Type
import this
. Que voyez-vous? Le Zen de Python. Quel est le dernier et probablement le plus peu de sagesse dans ce texte...?En forçant l'utilisation de barenames où les noms qualifiés sont donc infiniment préférable, vous êtes essentiellement faire de la très en face de de cette sage recommandation: au lieu d'admirer la grandeur et la honkingtude des espaces de noms, et de faire plus de ceux-ci, vous êtes briser deux parfaitement bon et prêt-à-utiliser des espaces de noms (que du module que vous importez, et que de la portée lexicale vous êtes l'importer) pour en faire un seul, impie, buggy, lent, rigide, inutilisable mess.
Si je pouvais revenir en arrière et changer un début de la conception de décision en Python (c'est un choix difficile, parce que l'utilisation de
def
et surtoutlambda
pour du Javascript donc beaucoup plus lisible appelsfunction
est une seconde près;-), je rétroactivement essuyer lesimport *
idée de Guido de l'esprit. Aucun montant de la présumé commodité pour l'exploration à l'invite interactive peut équilibrer la quantité de mal qu'il est forgé...!-)import *
et si vous êtes pleinement conscient de tous les modules importés, pourquoi éliminer la commodité? Bien sûr, il devrait être découragé dans un projet de plus d'un des ingénieurs.... import *
est une exception malheureuse. Il suffit de regarder l'ensemble de ses occurrences sur AINSI, par exemple, et vous allez commencer à voir ce qu'est un terrain fertile pour les bugs, les difficultés et les perplexités il est. Vous voulez de la concision à tout prix? Ensuite, Python n'est pas pour vous-puissance, la clarté, l'élégance, oui, l'extrême concision, n.... import *
, j'ai beaucoup préfèrent toujours importer un module (jamais un paquet, jamais une classe ou d'une fonction dans un module) -- Google guide de style pour Python s'engage, par le chemin, et il a fait de la "navigation" grâce au partage d'un code de millions de lignes de code incroyablement plus facile sur vous-même, et sur des outils commectags
qui à son tour vous aider à bien mieux comme ça;-).import *
dans une telle situation. Mon point est (à nouveau): pour l'utilisation interactive ou pour votre projet côté où vous savez exactement ce qui est importé dans chaque module pour lequel vous êtes à l'aide de l'expression,import *
ne devrait pas être rejetée.import *
peut être autorisé pour un projet plus important est lors du chargement d'un canoniques fichier de config, dire <projet>/config.py pour un projet composé uniquement de lettres majuscules variables. Si la config contient des centaines de majuscules, de variables et d'autres .py fichiers sont, par le code de la convention, de ne pas utiliser les majuscules uniquement des variables,from <project>/config import *
doit être acceptée comme une exception, car il sera tedius de type<project>.config.<varname>
pour chaque variable de config.import *
est utile pour la fusion des modules --tkinter
etttk
en sont les meilleurs exemples. Juste parce que reçoit maltraité et abusé de ne pas faire de faute.La notes de version pour Python 2.1 semblent expliquer pourquoi cette limitation existe:
import *
être rendue possible que si l'octet compilateur fonctionne le <module> dansfrom <module> import *
au moment de la compilation de sorte qu'il sait toutes les variables et les fonctions contenues dans le module? Pourquoi ne serait-il pas le faire?<module>
peut ne pas exister lorsque le code contenant l'instruction d'importation est compilé. Ou l'ensemble des variables à importer peuvent changer entre "compilation" et "temps d'exécution".Il n'est pas interdit, parce que...
... c'est de l'avoir sous la main des scripts shell et à explorer.
...mais vous ne devez pas garder à de graves code
Il n'est pas interdit à tous. Il fonctionne très bien, mais vous obtenez un avertissement parce que c'est généralement une mauvaise idée (pour des raisons autres ont disparu dans). Vous pouvez, si vous le souhaitez, supprimer l'avertissement; les avertissements module est ce que vous voulez pour que.
d'autres ont donné en profondeur les réponses, je vais vous donner un bref aperçu de la réponse de ma compréhension.. lors de l'utilisation de vous rendre, de sorte que vous pouvez appeler directement une fonction dans ce module vous importés sans faire modulename.functioname (vous pouvez les appeler "nomfonction") cela crée des problèmes si vous avez 2 fonctions du même nom dans différents modules et peut aussi créer de la confusion lorsque l'on traite avec beaucoup de fonctions que vous ne savez pas quel objet/module à laquelle il appartient (du point de vue de quelqu'un qui cherche déjà écrit du code qui n'est pas familier avec elle)