Estou dando uma olhada em como funciona o sistema de modelos no django e percebi algo que não entendo.
Eu sei que você cria um __init__.py
arquivo vazio para especificar que o diretório atual é um pacote. E que você pode definir alguma variável __init__.py
para que import * funcione corretamente.
Mas django adiciona um monte de instruções from ... import ... e define um monte de classes em __init__.py
. Por quê? Isso não faz com que as coisas pareçam confusas? Existe um motivo que requer este código __init__.py
?
python
initialization
package
Erik
fonte
fonte
__init__.py
django 1.8. Era para uma versão mais antiga? se sim qual versão?Respostas:
Todas as importações em
__init__.py
são disponibilizadas quando você importa 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
__init__.py
é executado na primeira vez que você importa qualquer módulo desse diretório. Portanto, normalmente é um bom lugar para colocar qualquer código de inicialização no nível do pacote.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í-lo porimport datetime
, então, em nosso nível superior,test.py
esses dois snippets funcionarão:import dir print dir.datetime.datetime.now()
e
import dir.some_module_in_dir print dir.datetime.datetime.now()
O resultado final é: todos os nomes atribuídos
__init__.py
, sejam módulos importados, funções ou classes, estão automaticamente disponíveis no namespace do pacote sempre que você importar o pacote ou um módulo do pacote.fonte
__init__.py
Eu realmente não considero o código de inicialização dessas classes (mas talvez eu esteja errado sobre isso).__init__.py
implicitamente. Ao importar os módulos internos__init__.py
, você está criando importações cíclicas. O__init__.py
não será executado totalmente antes de tal importação. É mais seguro ficar__init__.py
vazio.__init__.py
arquivos. Se você tivesse um arquivodir/other.py
que tivesse algo parecido comfrom datetime import datetime
você também seria capaz de ligardir.other.datetime.now()
ou até mesmofrom dir.other import datetime
.É apenas uma preferência pessoal, na verdade, e tem a ver com o layout de seus módulos Python.
Digamos que você tenha um módulo chamado
erikutils
. Pode ser um módulo de duas maneiras: você tem um arquivo chamado erikutils.py em seu computadorsys.path
ou um diretório chamado erikutils em seusys.path
com um__init__.py
arquivo vazio dentro dele. Então, digamos que você tem um monte de módulos chamadosfileutils
,procutils
,parseutils
e você quer aqueles para ser sub-módulos menoreserikutils
. Então, você faz alguns arquivos .py chamados fileutils.py , procutils.py e parseutils.py :Talvez você tem algumas funções que simplesmente não pertencem nos
fileutils
,procutils
ouparseutils
módulos. E digamos que você não queira criar um novo módulo chamadomiscutils
. E, você gostaria de poder chamar a função assim:ao invés de fazer
Portanto, como o
erikutils
módulo é um diretório, não um arquivo, temos que definir suas funções dentro do__init__.py
arquivo.Em django, o melhor exemplo que posso pensar é
django.db.models.fields
. TODAS as classes django * Field são definidas no__init__.py
arquivo no diretório django / db / models / fields . Eu acho que eles fizeram isso porque não queria empinar tudo em uma hipotética / db / modelos / fields.py django modelo, para que eles dividi-lo para fora em algumas sub-módulos ( related.py , files.py , por exemplo) e eles colaram as definições de * Field feitas no próprio módulo de campos (portanto,__init__.py
).fonte
something
pode ser um módulo externo, dir. algo ainda funcionará. Obrigado pelo comentário, irei editar meu post para deixar mais claro.Usar o
__init__.py
arquivo permite que você torne a estrutura interna do pacote invisível de fora. Se a estrutura interna mudar (por exemplo, porque você dividiu um módulo de gordura em dois), você só precisa ajustar o__init__.py
arquivo, mas não o código que depende do pacote. Você também pode tornar partes do seu pacote invisíveis, por exemplo, se não estiverem prontas para uso geral.Observe que você pode usar o
del
comando, então um típico__init__.py
pode ser assim:from somemodule import some_function1, some_function2, SomeObject del somemodule
Agora, se você decidir dividir,
somemodule
o novo__init__.py
pode ser:from somemodule1 import some_function1, some_function2 from somemodule2 import SomeObject del somemodule1 del somemodule2
Do lado de fora, a embalagem ainda parece exatamente como antes.
fonte
import <pack>.somemodule1
diretamente. Você só pode importar de<pack>
objetos definidos ou importados em seus__init__.py
submódulos e submódulos não excluídos.