Tentei encontrar um guia abrangente sobre se é melhor usar import module
ou from module import
? Acabei de começar com Python e estou tentando começar com as melhores práticas em mente.
Basicamente, eu estava esperando se alguém poderia compartilhar suas experiências, o que as preferências de outros desenvolvedores têm e qual é a melhor maneira de evitar armadilhas no caminho?
python
python-import
Filip Dupanović
fonte
fonte
from … import …
sintaxe no Python e 'módulo de importação' vs. 'da função de importação de módulo''from module import X,Y,Z
vs'from module import *
. Este último polui seu espaço para nome e pode fornecer resultados imprevisíveis, dependendo do que está acontecendo no módulo. O pior ainda está acontecendofrom module import *
com vários módulos.Respostas:
A diferença entre
import module
efrom module import foo
é principalmente subjetiva. Escolha o que você mais gosta e seja consistente em seu uso. Aqui estão alguns pontos para ajudá-lo a decidir.import module
import
declarações. Não é necessário adicionar importações adicionais para começar a usar outro item do módulomodule.foo
seu código pode ser entediante e redundante (o tédio pode ser minimizado usandoimport module as mo
e digitandomo.foo
)from module import foo
foo
import
declaraçãofoo
. Por exemplo, é menos claro o queceil()
faz em comparação commath.ceil()
Qualquer um dos métodos é aceitável, mas não use
from module import *
.Para qualquer conjunto grande de códigos razoável, se você
import *
provavelmente o cimentará no módulo, não poderá ser removido. Isso ocorre porque é difícil determinar quais itens usados no código são provenientes de 'module', facilitando chegar ao ponto em que você acha que não usaimport
mais, mas é extremamente difícil ter certeza.fonte
from module import *
pode ser particularmente útil, se usá-lo como:if(windows):\n\t from module_win import * \n else: \n\t from module_lin import *
. Em seguida, seu módulo pai pode potencialmente conter nomes de funções independentes do SO, se os nomes de função em module_lin e module_win tiverem os mesmos nomes. É como herdar condicionalmente qualquer uma das classes.Há outro detalhe aqui, não mencionado, relacionado à gravação em um módulo. Concedido isso pode não ser muito comum, mas eu preciso disso de tempos em tempos.
Devido à maneira como as referências e a associação de nomes funcionam no Python, se você deseja atualizar algum símbolo em um módulo, diga foo.bar, de fora desse módulo, e tenha outro código de importação "veja" essa alteração, você deve importar certo caminho. Por exemplo:
módulo foo:
módulo a:
módulo b:
No entanto, se você importar nomes de símbolos em vez de nomes de módulos, isso não funcionará.
Por exemplo, se eu fizer isso no módulo a:
Nenhum código fora de a verá a barra como "laranjas" porque minha configuração de barra afetou apenas o nome "barra" dentro do módulo a, não "alcançou" o objeto do módulo foo e atualizou sua "barra".
fonte
Mesmo que muitas pessoas já tenham explicado sobre o
import
vsimport from
, quero tentar explicar um pouco mais sobre o que acontece sob o capô e onde estão todos os lugares em que ele muda.import foo
:Importa
foo
e cria uma referência a esse módulo no espaço para nome atual. Em seguida, você precisa definir o caminho completo do módulo para acessar um atributo ou método específico de dentro do módulo.Por exemplo,
foo.bar
mas nãobar
from foo import bar
:Importa
foo
e cria referências a todos os membros listados (bar
). Não define a variávelfoo
.Por exemplo,
bar
mas nãobaz
oufoo.baz
from foo import *
:Importa
foo
e cria referências a todos os objetos públicos definidos por esse módulo no espaço para nome atual (tudo listado__all__
se__all__
existir, caso contrário, tudo o que não começa_
). Não define a variávelfoo
.Por exemplo,
bar
ebaz
mas não_qux
oufoo._qux
.Agora vamos ver quando fazemos
import X.Y
:Verifique
sys.modules
com nomeos
eos.path
:Os dicionários de verificação
globals()
elocals()
namespace comos
eos.path
:A partir do exemplo acima, descobrimos que apenas
os
é inserido no espaço para nome local e global. Portanto, devemos poder usar:Mas não
path
.Depois de excluir o
os
espaço de nomes from locals (), você não poderá acessaros
,os.path
mesmo que eles existam em sys.modules:Agora vamos falar sobre
import from
:from
:Verifique
sys.modules
comos
eos.path
:Descobrimos que em
sys.modules
que encontramos o mesmo que antes, usandoimport name
OK, cheque de deixar como ele se parece em
locals()
eglobals()
namespace dicts:Você pode acessar usando o nome
path
não poros.path
:Vamos excluir 'path' de
locals()
:Um exemplo final usando um alias:
E nenhum caminho definido:
fonte
as SYMBOL
muda como essa resposta funciona?As duas formas são suportadas por um motivo: há momentos em que uma é mais apropriada que a outra.
import module
: nice quando você estiver usando muitos bits do módulo. A desvantagem é que você precisará qualificar cada referência com o nome do módulo.from module import ...
: bom que itens importados sejam utilizáveis diretamente sem o prefixo do nome do módulo. A desvantagem é que você deve listar cada coisa que usa e que não está claro no código de onde algo veio.Qual usar depende do que torna o código claro e legível e tem mais do que um pouco de preferência pessoal. Eu me inclino em
import module
geral, porque no código é muito claro de onde veio um objeto ou função. Eu usofrom module import ...
quando estou usando algum objeto / função de um monte no código.fonte
from M import X
e ainda obter o benefício de usar os qualificadores de alguma forma? Parece que você poderia obter o melhor dos dois mundos se ainda pudesse fazerM.X
isso após a importação.class m: from something.too.long import x, y, z
. Realmente não recomendaria isso.Eu pessoalmente sempre uso
e depois acessar tudo como
etc. O motivo é que, ao mesmo tempo, você tem uma chamada curta e define claramente o espaço para nome do módulo de cada rotina, algo que é muito útil se você precisar procurar o uso de um determinado módulo em sua fonte.
Escusado será dizer que não use a importação *, pois polui seu espaço de nome e não informa de onde vem uma determinada função (de qual módulo)
Obviamente, você pode ter problemas se tiver o mesmo nome de módulo para dois módulos diferentes em dois pacotes diferentes, como
Nesse caso, é claro que você se depara com problemas, mas há uma forte dica de que o layout do seu pacote é defeituoso e é necessário repensá-lo.
fonte
É melhor quando você usará muitas funções do módulo.
É melhor quando você deseja evitar poluir o espaço para nome global com todas as funções e tipos de um módulo quando você só precisa
function
.fonte
Acabei de descobrir mais uma diferença sutil entre esses dois métodos.
Se o módulo
foo
usa uma seguinte importação:O módulo
bar
pode, por engano, usarcount
como se tivesse sido definido emfoo
, não emitertools
:Se
foo
usa:o erro ainda é possível, mas menos provável de ser cometido.
bar
precisa de:Isso me causou alguns problemas. Eu tinha um módulo que, por engano, importou uma exceção de um módulo que não o definiu, apenas o importou de outro módulo (usando
from module import SomeException
). Quando a importação não era mais necessária e removida, o módulo incorreto foi interrompido.fonte
Aqui está outra diferença não mencionada. Isso é copiado literalmente em http://docs.python.org/2/tutorial/modules.html
Observe que ao usar
o item pode ser um submódulo (ou subpacote) do pacote ou outro nome definido no pacote, como uma função, classe ou variável. A instrução de importação primeiro testa se o item está definido no pacote; caso contrário, assume que é um módulo e tenta carregá-lo. Se não conseguir encontrá-lo, uma exceção ImportError será gerada.
Ao contrário, ao usar sintaxe como
cada item, exceto o último, deve ser um pacote; o último item pode ser um módulo ou um pacote, mas não pode ser uma classe ou função ou variável definida no item anterior.
fonte
Como também sou iniciante, tentarei explicar isso de uma maneira simples: No Python, temos três tipos de
import
declarações que são:1. Importações genéricas:
esse tipo de importação é meu favorito pessoal, a única desvantagem dessa técnica de importação é que, se você precisar usar a função de qualquer módulo, deverá usar a seguinte sintaxe:
é claro, aumenta o esforço de digitação, mas como iniciante, ajudará você a acompanhar o módulo e as funções associadas a ele (um bom editor de texto reduzirá significativamente o esforço de digitação e é recomendado).
O esforço de digitação pode ser reduzido ainda mais usando esta declaração de importação:
agora, em vez de usar,
math.sqrt()
você pode usarm.sqrt()
.2. Importações de funções:
esse tipo de importação é mais adequado se o seu código precisar acessar apenas uma ou poucas funções do módulo, mas para usar qualquer novo item do módulo, é necessário atualizar a instrução de importação.
3. Importações universais:
Embora reduza significativamente o esforço de digitação, mas não é recomendado, pois ele preencherá seu código com várias funções do módulo e seu nome poderá entrar em conflito com o nome das funções definidas pelo usuário. exemplo:
Se você possui uma função do seu próprio sqrt nomeado e importa matemática, sua função é segura: existe o sqrt e o math.sqrt. Se você fizer a importação matemática *, no entanto, você terá um problema: duas funções diferentes com o mesmo nome. Fonte: Codecademy
fonte
Com
import
, o token deve ser um módulo (um arquivo que contém comandos Python) ou um pacote (uma pasta quesys.path
contém um arquivo__init__.py
).Quando há subpacotes:
os requisitos para pasta (pacote) ou arquivo (módulo) são os mesmos, mas a pasta ou o arquivo deve estar dentro do
package2
qual deve estar dentropackage1
e ambospackage1
epackage2
devem conter__init__.py
arquivos. https://docs.python.org/2/tutorial/modules.htmlCom o
from
estilo de importação:o pacote ou módulo entra no espaço para nome do arquivo que contém a
import
instrução comomodule
(oupackage
) em vez depackage1.package2.module
. Você sempre pode vincular a um nome mais conveniente:Somente o
from
estilo de importação permite nomear uma função ou variável específica:é permitido, mas
não é permitido.
fonte
Para acrescentar ao que as pessoas disseram
from x import *
: além de tornar mais difícil saber de onde os nomes vieram, isso desencadeia verificadores de código como o Pylint. Eles reportarão esses nomes como variáveis indefinidas.fonte
Minha própria resposta a isso depende principalmente de quantos módulos diferentes eu vou usar. Se eu vou usar apenas um ou dois, usarei frequentemente
from
...import
uma vez que gera menos pressionamentos de tecla no restante do arquivo, mas se vou usar muitos módulos diferentes, prefiro apenasimport
porque isso significa que cada referência de módulo é auto-documentada. Eu posso ver de onde vem cada símbolo sem ter que caçar.Geralmente eu prefiro o estilo de auto-documentação de importação simples e só mudo para de .. import quando o número de vezes que eu tenho que digitar o nome do módulo cresce acima de 10 a 20, mesmo se houver apenas um módulo sendo importado.
fonte
Uma das diferenças significativas que descobri, que surpreendentemente ninguém falou, é que usando a importação simples você pode acessar
private variable
eprivate functions
do módulo importado, o que não é possível com a declaração from-import .Código na imagem:
setting.py
plain_importer.py
from_importer.py
fonte
Importar módulo - você não precisa de esforços adicionais para buscar outra coisa do módulo. Tem desvantagens, como digitação redundante
Importação de módulos de - menos digitação e mais controle sobre quais itens de um módulo podem ser acessados. Para usar um novo item do módulo, é necessário atualizar sua declaração de importação.
fonte
Existem alguns módulos internos que contêm principalmente funções simples ( base64 , matemática , sistema operacional , shutil , sys , time , ...) e é definitivamente uma boa prática vincular essas funções a algum espaço de nome e, assim, melhorar a legibilidade do seu código. Considere o quão mais difícil é entender o significado dessas funções sem o namespace:
do que quando eles estão vinculados a algum módulo:
Às vezes, você precisa do espaço para nome para evitar conflitos entre diferentes módulos ( json.load vs. pickle.load )
Por outro lado, existem alguns módulos que contêm principalmente classes ( ConfigParser , datetime , tempfile , zipfile , ...) e muitos deles fazem seus nomes de classe bastante auto-explicativo:
portanto, pode haver um debate sobre se o uso dessas classes com o espaço de nome do módulo adicional no seu código adiciona novas informações ou apenas aumenta o código.
fonte
Gostaria de acrescentar que há algumas coisas a considerar durante as chamadas de importação:
Eu tenho a seguinte estrutura:
main.py:
dis.dis mostra a diferença:
No final, eles parecem iguais (STORE_NAME é o resultado em cada exemplo), mas vale a pena notar se você precisar considerar as quatro importações circulares a seguir:
Exemplo 1
Isso funciona
exemplo2
Sem dados
exemplo3
Problema semelhante ... mas claramente de x import y não é o mesmo que importar import xy como y
exemplo4
Este também funciona
fonte
Esta é a minha estrutura de diretórios do meu diretório atual:
A
import
declaração lembra todos os nomes intermediários .Esses nomes devem ser qualificados:
A
from ... import ...
declaração lembra apenas o nome importado .Este nome não deve ser qualificado:
fonte
Como Jan Wrobel menciona, um aspecto das diferentes importações é o modo como as importações são divulgadas.
Módulo mymath
Uso de mymath :
Se eu importar
gcd
apenas para uso interno, não divulgá-lo aos usuários demymath
, isso pode ser inconveniente. Eu tenho isso com bastante frequência e, na maioria dos casos, quero "manter meus módulos limpos".Além da proposta de Jan Wrobel de ocultar um pouco mais isso
import math
, comecei a ocultar as importações da divulgação usando um sublinhado principal:Em projetos maiores, essa "melhor prática" permite controlar exatamente o que é divulgado para importações subsequentes e o que não é. Isso mantém meus módulos limpos e compensa em um determinado tamanho de projeto.
fonte