Pergunta

Estou tendo um olhar para a forma como o sistema modelo em Django funciona e eu observei algo que eu não entendo.

Eu sei que você criar um arquivo __init__.py vazio para especificar que o diretório atual é um pacote. E que você pode definir alguma variável em __init__.py para que import * funciona corretamente.

Mas Django adiciona um monte de de ... importação ... declarações e define um monte de aulas de __init__.py. Por quê? Isso não apenas fazer coisas olhar confuso? Existe uma razão que requer esse código em __init__.py?

Foi útil?

Solução

Todas as importações em __init__.py são disponibilizados quando você importar o pacote (diretório) que o contém.

Exemplo:

./dir/__init__.py:

import something

./test.py:

import dir
# can now use dir.something

EDIT: Esqueci de mencionar, o código no __init__.py executado na primeira vez que você importar qualquer módulo do diretório. Portanto, é normalmente um bom lugar para colocar qualquer código de nível de pacote de inicialização.

EDIT2: dgrant apontou para uma possível confusão no meu exemplo. Em __init__.py import something pode importar qualquer módulo, não é necessário a partir do pacote. Por exemplo, podemos substituí-la por import datetime, em seguida, na nossa test.py nível superior ambos os trechos funcionará:

import dir
print dir.datetime.datetime.now()

e

import dir.some_module_in_dir
print dir.datetime.datetime.now()

A linha inferior é: todos os nomes atribuídos em __init__.py, seja importado módulos, funções ou classes, estão automaticamente disponíveis no namespace do pacote sempre que você importar o pacote ou um módulo no pacote

.

Outras dicas

É preferência apenas pessoal realmente, e tem a ver com o layout dos módulos python.

Vamos dizer que você tem um módulo chamado erikutils. Há duas maneiras que ele pode ser um módulo, ou você tem um arquivo chamado erikutils.py em seu sys.path ou você tem um diretório chamado erikutils em seu sys.path com um vazio __init__.py arquivo dentro dela. Então digamos que você tem um monte de módulos chamados fileutils, procutils, parseutils e você quer aqueles para ser sub-módulos sob erikutils. Então, você faz alguns arquivos .py chamado fileutils.py , procutils.py e parseutils.py :

erikutils
  __init__.py
  fileutils.py
  procutils.py
  parseutils.py

Talvez você tem algumas funções que não se encaixasse nos módulos fileutils, procutils, ou parseutils. E digamos que você não se sentir como a criação de um novo módulo chamado miscutils. E, você gostaria de ser capaz de chamar a função assim:

erikutils.foo()
erikutils.bar()

em vez de fazer

erikutils.miscutils.foo()
erikutils.miscutils.bar()

Então, porque o módulo erikutils é um diretório, não um arquivo, temos que defini-lo de funções dentro do __init__.py arquivo.

No Django, o melhor exemplo que posso pensar é django.db.models.fields. TODO o Django * Aulas de campo são definidos no __init__.py no django / db / modelos / campos diretório. Eu acho que eles fizeram isso porque não queria empinar tudo em uma hipotética django / db / models / fields.py modelo, para que eles dividi-lo para fora em algumas sub-módulos ( relacionados. py , files.py , por exemplo) e eles enfiaram as feitas definições * o campo nos campos módulo em si (daí, __init__.py ).

Usando o arquivo __init__.py permite que você faça a estrutura do pacote interno invisível do lado de fora. Se as mudanças na estrutura interna (por exemplo, porque você dividir um módulo de gordura em dois) você só tem que ajustar o arquivo __init__.py, mas não o código que depende do pacote. Você também pode fazer partes do seu pacote invisível, por exemplo, se eles não estão prontos para o uso geral.

Note que você pode usar o comando del, portanto, um __init__.py típico pode ser parecido com isto:

from somemodule import some_function1, some_function2, SomeObject

del somemodule

Agora, se você decidir somemodule dividir o novo __init__.py poderia ser:

from somemodule1 import some_function1, some_function2
from somemodule2 import SomeObject

del somemodule1
del somemodule2

Do lado de fora do pacote ainda parece exatamente como antes.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top