'import module' vs. 'from module import function'

126

Eu sempre usei esse método:

from sys import argv

e use argv com apenas argv . Mas há uma convenção de usar isso:

import sys

e usando o argv por sys.argv

O segundo método torna o código auto documentado e eu (realmente) adiro a ele. Mas a razão pela qual eu prefiro o primeiro método é que ele é rápido porque estamos importando apenas a função que é necessária em vez de importar o módulo inteiro (que contém mais funções inúteis que o python perderá tempo importando-as). Note que eu preciso apenas de argv e todas as outras funções do sistema são inúteis para mim.

Então, minhas perguntas são. O primeiro método realmente torna o script rápido? Qual método é mais preferido? Por quê?

    
por Santosh Kumar 18.02.2013 / 06:43
fonte

8 respostas

160

Importar o módulo não desperdiça nada ; o módulo é sempre totalmente importado (para o mapeamento sys.modules ), de modo que você use import sys ou from sys import argv não faz nenhuma probabilidade.

A única diferença entre as duas declarações é o nome que está vinculado; import sys liga o nome sys ao módulo (assim sys - > sys.modules['sys'] ), enquanto from sys import argv liga um nome diferente, argv , apontando diretamente para o atributo contido dentro do módulo (assim argv - > sys.modules['sys'].argv ). O resto do módulo sys ainda está lá, quer você use qualquer outra coisa do módulo ou não.

Também não há diferença de desempenho entre as duas abordagens. Sim, sys.argv tem que procurar duas coisas; ele precisa procurar sys em seu namespace global (localiza o módulo) e, em seguida, procurar o atributo argv . E sim, usando from sys import argv você pode ignorar a pesquisa de atributos, já que você já tem uma referência direta ao atributo. Mas a declaração import ainda tem que fazer esse trabalho, ele procura o mesmo atributo ao importar, e você só precisará usar argv uma vez . Se você tivesse que usar argv milhares de vezes em um loop, talvez pudesse fazer a diferença, mas, neste caso específico, isso não acontece.

A escolha entre um ou outro deve ser baseada em estilo de codificação .

Em um módulo grande , eu certamente usaria import sys ; a documentação do código é importante, e usar sys.argv em algum lugar em um módulo grande torna muito mais claro o que você está se referindo do que apenas argv jamais faria.

Se o único local em que você usa argv está em '__main__' para chamar uma função main() , use from sys import argv se você se sentir mais feliz com isso:

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

Eu ainda usaria import sys lá. Todas as coisas são iguais (e são, exatamente, em termos de desempenho e número de caracteres usados para escrevê-lo), isso é mais fácil para mim.

Se você estiver importando algo mais , então talvez o desempenho entre em ação. Mas somente se você usar um nome específico em um módulo muitas vezes por , em um loop crítico, por exemplo. Mas criar um nome local (dentro de uma função) será ainda mais rápido:

 import somemodule

 def somefunction():
      localname = somemodule.somefunctionorother
      while test:
          # huge, critical loop
          foo = localname(bar)
    
por 18.02.2013 / 19:17
fonte
38

Há dois motivos para usar import module em vez de from module import function .

Primeiro é o namespace. Importar uma função para o espaço de nomes global arrisca colisões de nomes.

Segundo, isso não é relevante para os módulos padrão, mas significativo para seus próprios módulos, especialmente durante o desenvolvimento. É a opção para reload() a module. Considere isto:

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

Por outro lado

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

Quanto à velocidade ...

we are importing only the function that is needed rather than import the whole module (which contains more useless functions which python will waste time importing them)

Se você importar um módulo ou importar uma função de um módulo, o Python analisará todo o módulo. De qualquer forma, o módulo é importado. "Importar uma função" nada mais é do que ligar a função a um nome. De fato, import module é menos trabalho para o intérprete do que from module import func .

    
por 18.02.2013 / 10:09
fonte
17

Na minha opinião, usar import regular melhora a legibilidade. Ao rever o código Python, eu gosto de ver de onde a determinada função ou classe vem exatamente onde é usada. Isso me impede de rolar para o topo do módulo para obter essa informação.

Quanto aos nomes dos módulos longos, apenas uso a palavra-chave as e atribuo-lhes nomes curtos:

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

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

Como uma exceção, sempre uso a notação from module import something quando lido com o módulo __future__ . Você não pode fazer isso de outra maneira quando quiser que todas as strings sejam unicode por padrão no Python 2, por exemplo,

from __future__ import unicode_literals
from __future__ import print_function
    
por 04.03.2015 / 18:25
fonte
16

Eu uso from import s sempre que melhora a legibilidade. Por exemplo, eu prefiro (ponto e vírgula são apenas para economizar espaço aqui):

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

em vez de:

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

O último é mais difícil de ler (e escrever) para mim porque contém muita informação redundante. Além disso, é útil saber de antemão quais partes de um módulo estou usando.

Eu prefiro import s regular se estou usando muitos nomes curtos de um módulo:

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

Ou se um nome é tão genérico que não faz sentido fora do seu espaço de nomes:

import json
json.loads(foo)

from json import loads
loads(foo)  # potentially confusing
    
por 18.02.2013 / 19:42
fonte
4

Embora import sys e from sys import agrv importem o módulo sys inteiro, o último usa a vinculação de nome, portanto, somente o módulo argv está acessível para o resto do código.

Para algumas pessoas, este seria o estilo preferido, uma vez que só torna acessível a função explicitamente declarada.

No entanto, ele introduz possíveis conflitos de nome. E se você tivesse outro módulo chamado argv ? Observe que você também pode importar explicitamente a função e renomear com from sys import argv as sys_argv , uma convenção que atende à importação explícita e tem menor probabilidade de gerar colisões de espaço de nome.

    
por 20.02.2013 / 05:49
fonte
1

Recentemente, fiz essa pergunta a mim mesmo. Eu cronometrei os diferentes métodos.

solicita biblioteca

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

biblioteca 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

biblioteca 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

biblioteca 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

Parece-me que existe uma ligeira diferença no desempenho.

    
por 07.01.2015 / 22:23
fonte
-1

Olhando fragmentos de código publicados, importar módulos inteiros e referindo-se a module.function é praticamente o padrão, pelo menos para módulos padrão. A única exceção parece ser datetime

from datetime import datetime, timedelta

para que você possa dizer datetime.now() em vez de datetime.datetime.now() .

Se você está preocupado com o desempenho, sempre pode dizer (por exemplo)

argv = sys.argv

e, em seguida, faça seu código crítico de desempenho desde que a consulta do módulo já esteja concluída. No entanto, embora isso funcione com funções / métodos, a maioria dos IDE ficará confusa e não exibirá (por exemplo) um link / assinatura de origem para a função quando ela é atribuída a uma variável.

    
por 03.06.2016 / 18:01
fonte
-2

Eu só quero adicionar isso se você fizer algo como

from math import sin

(ou qualquer outra biblioteca interna como sys ou posix ), então sin será incluído na documentação do seu módulo (ou seja, quando você executar >>> help(mymodule) ou $ pydoc3 mymodule . Para evitar isso, , import usando:

import math
from math import sin as _sin

PS: uma biblioteca interna é aquela compilada a partir do código C e incluída no Python. argparse , os e io não são pacotes internos

    
por 03.09.2017 / 07:33
fonte

Tags