Sempre usei este método:
from sys import argv
e use argv
com apenas argv . Mas há uma convenção de usar isso:
import sys
e usar o argv por sys.argv
O segundo método torna o código autodocumentado e eu (realmente) aderi a ele. Mas a razão pela qual prefiro o primeiro método é que ele é rápido porque estamos importando apenas a função 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). Observe que preciso apenas do argv e todas as outras funções do sys são inúteis para mim.
Então, minhas perguntas são. O primeiro método realmente torna o script mais rápido? Qual método é mais preferido? Por quê?
Comentários
Resposta
Importar o módulo não desperdiça nada ; o módulo é sempre totalmente importado (para o mapeamento sys.modules
), então se você usar import sys
ou from sys import argv
não faz diferença.
A única diferença entre as duas declarações é o nome que está vinculado; import sys
vincula o nome sys
para o módulo (então sys
-> sys.modules["sys"]
), enquanto from sys import argv
liga um nome diferente, argv
, apontando diretamente para o atributo contido dentro do módulo (então argv
-> sys.modules["sys"].argv
). O resto do O módulo e sys
ainda está lá, quer você use alguma coisa do módulo ou não.
Também não há diferença de desempenho entre as duas abordagens. Sim, sys.argv
precisa pesquisar duas coisas; ele precisa procurar sys
em seu namespace global (encontra o módulo) e, em seguida, procurar o atributo argv
. E sim, usando from sys import argv
você pode pular a pesquisa de atributo, uma vez que você já tem uma referência direta ao atributo. Mas a instrução import
ainda precisa fazer esse trabalho, ela procura o mesmo atributo durante a importação 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 realmente não faz .
A escolha entre um ou outro deve ser baseada no estilo de codificação .
Em um módulo grande , Eu certamente usaria import sys
; a documentação do código é importante e o uso de sys.argv
em um módulo grande torna muito mais claro a que você está se referindo do que apenas argv
faria.
Se o único lugar que você usar argv
for um "__main__"
bloco para chamar um main()
função, por suposto use from sys import argv
se você se sentir mais feliz com isso:
if __name__ == "__main__": from sys import argv main(argv)
I “d ainda uso import sys
lá eu mesmo. Todas as coisas sendo iguais (e são, exatamente, em termos de desempenho e número de caracteres usados para escrevê-lo) , isso é apenas mais fácil para mim.
Se você estiver importando algo diferente por completo, talvez o desempenho entre em jogo. Mas apenas se você usar um nome específico em um módulo muitas vezes , 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)
Comentários
- Também há a situação em que você tem um pacote com subpacotes ou módulos que expõe um atributo de um desses subpacotes / módulos no pacote de nível superior. Usar
from...import
permite que você façapackage.attribute
em vez depackage.subpackage_or_module.attribute
, o que pode ser útil se você tem agrupamentos lógicos ou conceituais dentro do pacote, mas deseja tornar as coisas um pouco mais convenientes para os usuários do seu pacote. (numpy
faz algo assim, eu acredito.) - No django você tem muitos locais onde coisas como
from django.core.management.base import BaseCommand
são melhores e qualquer outra coisa (especialmenteimport django
) levaria a um código ilegível. Portanto, embora eu goste dessa resposta, acho que existem algumas bibliotecas (e especialmente alguns frameworks) nas quais a convenção é violar a importação básica.Como sempre, use seu julgamento sobre o que é melhor em uma determinada situação. Mas erre pelo lado explícito (em outras palavras, concordo na maior parte). - @JAB: você ainda pode usar
import ... as
para encontrar o pacote para um nome diferente:import package.subpackage_or_module as shortname
.from parent import sub
faz, essencialmente, a mesma coisa. -
so wether you use import sys or from sys import argv makes no odds
este parece não ser o caso com o IDLE. apenas importar o módulo não importa suas funções e posso chamá-lo no shell IDLE apenas por < módulo >. < function > nome - @Suncatcher: leia minha resposta por completo. A frase que você cita fala sobre quanto está sendo importado, não qual nome está vinculado. Isso ‘ é coberto em outra parte da resposta.
Resposta
Há duas razões a favor do uso de import module
em vez de from module import function
.
O primeiro é o namespace. Importar uma função para o namespace global arrisca colisões de nomes.
Em segundo lugar, não é tão relevante para os módulos padrão, mas significativo para seus próprios módulos, especialmente durante o desenvolvimento. É a opção de reload()
um módulo. Considere o seguinte:
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 .. .
estamos importando apenas a função 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)
Independentemente de 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 vincular a função a um nome. Na verdade, import module
dá menos trabalho para o intérprete do que from module import func
.
Comentários
- reload () era um embutido no Python 2; esse não é mais o caso do Python 3.
- Achei que também havia implicações relacionadas às dependências de importação circulares?
Resposta
Eu uso from import
s sempre que melhora a legibilidade. Por exemplo, eu prefiro (ponto-e-vírgulas 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 muitas informações redundantes. Além disso, é útil saber com antecedência quais partes de um módulo estou usando.
Eu prefiro import
s regulares se estou usando muitos de nomes curtos de um módulo:
import sys sys.argv; sys.stderr; sys.exit()
Ou se um nome for tão genérico que não faça sentido fora de seu namespace:
import json json.loads(foo) from json import loads loads(foo) # potentially confusing
Comentários
- Esta é minha resposta favorita. ‘ Explícito é melhor do que implícito ‘ às vezes entra em conflito com legibilidade, simplicidade e DRY. Especialmente ao usar uma estrutura como Django.
Resposta
Na minha opinião, usando melhora a legibilidade. Ao revisar o código Python, gosto de ver de onde vem a função ou classe fornecida exatamente de onde é usada. Isso me poupa de rolar para o topo do módulo para obter essa informação.
Quanto aos nomes de módulo longos, eu apenas uso a palavra-chave as
e forneço-lhes breves aliases:
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 exceção, sempre uso a notação from module import something
quando lido com __future__
. Você simplesmente não pode fazer de outra maneira quando deseja que todas as strings sejam Unicode por padrão no Python 2, por exemplo,
from __future__ import unicode_literals from __future__ import print_function
Comentários
- Amém! ” importar porque ” é uma combinação vencedora 🙂
Resposta
Embora import sys
e from sys import agrv
ambos importam todo o módulo sys
, o último usa vinculação de nome para que apenas o módulo argv
esteja acessível para o restante do código.
Para algumas pessoas, este seria o estilo preferido, pois torna acessível apenas a função que você declarou explicitamente.
No entanto, introduz conflitos de nomes em potencial. 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 é menos provável de fornecer espaço de nome colisões.
Comentários
- Então, como
if sys_argv:
é melhor do queif sys.argv:
? Eu sei o que a segunda afirmação significa, não tenho ideia do que a primeira forma significa sem voltar para a importação bizarra.
Resposta
Recentemente, fiz esta pergunta para mim mesmo. Cronometrei os diferentes métodos.
Solicita a 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 que me que há uma ligeira diferença no desempenho.
Comentários
- Você está adicionando em uma pesquisa de atributo. Para comparar
import module
comfrom module import name
corretamente, adicione essa pesquisa de nome aoimport module
caso. Por exemplo. adicione a linhasys.argv
aoar
teste, etc. Ainda haverá uma diferença, porque o trabalho realizado é ligeiramente diferente, conforme bytecode diferente é gerado e codepaths diferentes são executados. - Observe que eu abordo diretamente essa diferença em minha resposta; haverá uma diferença entre usar
import sys
e usarsys.argv
milhares de vezes em um loop vs.from sys import argv
em seguida, usando apenasargv
. Mas você não ‘ t. Para coisas que você faz apenas uma vez no nível global do seu módulo, você realmente deve otimizar para legibilidade, não diferenças microscópicas de tempo. - Ahhhh! E eu pensei que estava no caminho certo! 🙂 Eu apenas esqueci sua resposta. Parece que eu me precipitei nessa. É bom sentir-se humilde.
Resposta
Examinando fragmentos de código publicados, importando 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
então você pode dizer datetime.now()
em vez de datetime.datetime.now()
.
Se você está preocupado com o desempenho, pode sempre dizer (por exemplo)
argv = sys.argv
e, em seguida, faça seu código crítico de desempenho, uma vez que a pesquisa do módulo já foi feita. No entanto, embora isso funcione com funções / métodos, a maioria dos IDE se confundirá e não exibirá (por exemplo) um link / assinatura de origem para a função quando for atribuída a uma variável.
Resposta
Só quero acrescentar que se você fizer algo como
from math import sin
(ou qualquer outra biblioteca integrada como sys
ou posix
), então sin
ser incluído na documentação do seu módulo (ou seja, quando você fizer >>> help(mymodule)
ou $ pydoc3 mymodule
. Para evitar isso, importe usando:
import math from math import sin as _sin
PS: uma biblioteca integrada é aquela compilada a partir do código C e incluída no Python. argparse
, os
e io
não são pacotes integrados
from … import …
sintaxe em Python