web-dev-qa-db-fra.com

'module d'importation' vs 'à partir de la fonction d'importation de module'

J'ai toujours utilisé cette méthode:

from sys import argv

et utilisez argv avec juste argv. Mais il existe une convention d'utilisation de ceci:

import sys

et en utilisant l'argv par sys.argv

La deuxième méthode rend le code auto-documenté et j'y adhère (vraiment) . Mais la raison pour laquelle je préfère la première méthode est qu'elle est rapide car nous importons uniquement la fonction nécessaire plutôt que d'importer le module entier (qui contient plus de fonctions inutiles qui python perdra du temps à les importer) Notez que je n'ai besoin que d'argv et toutes les autres fonctions de sys sont inutiles pour moi.

Donc mes questions sont. La première méthode accélère-t-elle vraiment le script? Quelle méthode est préférée? Pourquoi?

157
Santosh Kumar

L'importation du module ne gaspille pas n'importe quoi; le module est toujours entièrement importé (dans le mappage sys.modules), donc que vous utilisiez import sys ou from sys import argv n'a aucune chance.

La seule différence entre les deux instructions est le nom qui est lié; import sys Lie le nom sys au module (donc sys -> sys.modules['sys']), Tandis que from sys import argv Lie un nom différent, argv, pointant directement sur l'attribut contenu à l'intérieur du module (donc argv -> sys.modules['sys'].argv). Le reste du module sys est toujours là, que vous utilisiez autre chose du module ou non.

Il n'y a pas non plus de différence de performances entre les deux approches. Oui, sys.argv Doit rechercher deux choses; il doit rechercher sys dans votre espace de noms global (trouve le module), puis rechercher l'attribut argv. Et oui, en utilisant from sys import argv Vous pouvez ignorer la recherche d'attribut, car vous avez déjà une référence directe à l'attribut. Mais l'instruction import doit encore faire ce travail, elle recherche le même attribut lors de l'importation, et vous n'aurez besoin que d'utiliser argvne fois. Si vous deviez utiliser argv des milliers de fois dans une boucle, cela pourrait peut-être faire la différence, mais dans ce cas précis, ce n'est vraiment pas le cas.

Le choix entre l'un ou l'autre doit alors être basé sur style de codage à la place.

Dans un module grand, j'utiliserais certainement import sys; la documentation du code est importante, et l'utilisation de sys.argv quelque part dans un grand module rend plus clair ce à quoi vous faites référence que simplement argv.

Si le seul endroit où vous utilisez argv est dans un bloc '__main__' Pour appeler une fonction main(), utilisez par tous les moyens from sys import argv Si vous en êtes plus satisfait :

if __name__ == '__main__':
    from sys import argv
    main(argv)

J'utiliserais toujours import sys Moi-même. Toutes choses étant égales par ailleurs (et elles le sont exactement en termes de performances et nombre de caractères utilisés pour l'écrire), c'est plus simple pour moi.

Si vous importez quelque chose else tout à fait, alors peut-être que les performances entrent en jeu. Mais seulement si vous utilisez un nom spécifique dans un module plusieurs fois, dans une boucle critique par exemple. Mais la création d'un nom local (au sein d'une fonction) sera encore plus rapide:

 import somemodule

 def somefunction():
      localname = somemodule.somefunctionorother
      while test:
          # huge, critical loop
          foo = localname(bar)
184
Martijn Pieters

Il y a deux raisons pour utiliser import module Plutôt que from module import function.

Le premier est l'espace de noms. L'importation d'une fonction dans l'espace de noms global risque les collisions de noms.

La seconde n'est pas pertinente pour les modules standard, mais importante pour vos propres modules, en particulier pendant le développement. C'est l'option de reload() un module. Considère ceci:

from module import func
...
reload(module)
# func still points to the old code

D'autre part

import module
...
reload(module)
# module.func points to the new code

Quant à la vitesse ...

nous importons uniquement la fonction nécessaire plutôt que d'importer le module entier (qui contient plus de fonctions inutiles qui python perdra du temps à les importer)

Que vous importiez un module ou importiez une fonction à partir d'un module, Python analysera tout le module. Quoi qu'il en soit, le module est importé. "L'importation d'une fonction" n'est rien de plus que la liaison de la fonction à un En fait, import module représente moins de travail pour l'interprète que from module import func.

47
vartec

À mon avis, l'utilisation régulière de import améliore la lisibilité. Lorsque j'examine le code Python j'aime voir d'où vient la fonction ou la classe donnée là où elle est utilisée. Cela m'évite de faire défiler vers le haut du module pour obtenir ces informations.

En ce qui concerne les noms de modules longs, j'utilise simplement le mot clé as et je leur donne des alias courts:

import collections as col
import foomodule as foo
import twisted.internet.protocol as twip

my_dict = col.defaultdict()
foo.FooBar()
twip_fac = twip.Factory()

Par exception, j'utilise toujours le from module import something notation quand je traite avec __future__ module. Vous ne pouvez tout simplement pas le faire d'une autre manière lorsque vous souhaitez que toutes les chaînes soient unicode par défaut dans Python 2, par exemple.

from __future__ import unicode_literals
from __future__ import print_function
19
golem

J'utilise from imports chaque fois qu'il améliore la lisibilité. Par exemple, je préfère (les points-virgules ne servent qu'à économiser de l'espace ici):

from collections import defaultdict
from foomodule import FooBar, FooBaz
from twisted.internet.protocol import Factory
defaultdict(); FooBar(); FooBaz(); Factory()

au lieu de:

import collections
import foomodule
import twisted.internet.protocol
collections.defaultdict(); foomodule.FooBar(); foomodule.FooBaz()
twisted.internet.protocol.Factory()

Ce dernier est plus difficile à lire (et à écrire) pour moi car il contient tellement d'informations redondantes. De plus, il est utile de savoir à l'avance quelles parties d'un module j'utilise.

Je préfère les imports réguliers si j'utilise beaucoup de noms courts à partir d'un module:

import sys
sys.argv; sys.stderr; sys.exit()

Ou si un nom est si générique qu'il n'a pas de sens en dehors de son espace de noms:

import json
json.loads(foo)

from json import loads
loads(foo)  # potentially confusing
19
user76704

Bien que import sys et from sys import agrv les deux importent l'ensemble du module sys, ce dernier utilise la liaison de nom, de sorte que seul le module argv est accessible au reste du code.

Pour certaines personnes, ce serait le style préféré car il ne rend accessible que la fonction que vous avez explicitement indiquée.

Il introduit cependant des conflits de noms potentiels. Et si vous aviez un autre module nommé argv? Notez que vous pouvez également importer explicitement la fonction et renommer avec from sys import argv as sys_argv, une convention qui respecte l'importation explicite et est moins susceptible de donner lieu à des collisions d'espace de noms.

4
Duncan

Je me suis récemment posé cette question. J'ai chronométré les différentes méthodes.

bibliothèque de demandes

def r():
    import requests
    return 'hello'
timeit r() # output: 1000000 loops, best of 3: 1.55 µs per loop

def rg():
    from requests import get
    return 'hello'
timeit rg() # output: 100000 loops, best of 3: 2.53 µs per loop

bibliothèque beautifulsoup

def bs():
    import bs4
    return 'hello' 
timeit bs() # output: 1000000 loops, best of 3: 1.53 µs per loop

def be():
    from bs4 import BeautifulSoup
    return 'hello'
timeit be() # output: 100000 loops, best of 3: 2.59 µs per loop

bibliothèque json

def js():
    import json
    return 'hello'
timeit js() # output: 1000000 loops, best of 3: 1.53 µs per loop

def jl():
    from json import loads
    return 'hello'
timeit jl() # output: 100000 loops, best of 3: 2.56 µs per loop

bibliothèque sys

def s():
    import sys
    return 'hello'
timeit s() # output: 1000000 loops, best of 3: 1.55 µs per loop

def ar():
    from sys import argv
    return 'hello'
timeit ar() # output: 100000 loops, best of 3: 2.87 µs per loop

Il me semble que il y a une légère différence de performance.

1
tmthyjames