2008-09-23 19 views
75

Django'daki model sisteminin nasıl çalıştığına bakıyorum ve anlamadığım bir şeyi farkettim.__init__.py için kod ekleme

Geçerli dizinin bir paket olduğunu belirtmek için boş bir __init__.py dosyası oluşturduğunuzu biliyorum. Ve __init__.py'da bazı değişkenleri ayarlayabilirsiniz, böylece import * doğru şekilde çalışır.

Ancak django, __init__.py numaralı belgede bir grup ... içe aktarma ifadesi ekler ve bir grup dersi tanımlar. Niye ya? Bu işlerin dağınık görünmesine neden olmaz mı? Bu kodu __init__.py'da gerektiren bir neden var mı?

+13

Bu gerçekten Django ile ilgili değil mi? Evet, önce Django'da gördün, ama bu daha çok Python gibi bir şey gibi görünüyor - belki de Django etiketi gerçekten uygun değil. –

+0

'__init __. Py' django 1.8' da herhangi bir içe aktarma ifadesi göremiyorum. Bu eski bir sürüm için miydi? eğer öyleyse hangi versiyonu? –

cevap

67

__init__.py adresindeki tüm içe aktarma, içeriği içeren paketi (dizini) içe aktardığınızda kullanılabilir duruma gelir.

Örnek:

./dir/__init__.py:

import something 

./test.py:

import dir 
# can now use dir.something 

DÜZENLEME: söylemeyi unutmuşum, __init__.py kod o dizinden herhangi bir modülü ilk kez çalışır. Bu yüzden normalde paket düzeyinde bir başlatma kodu koymak için iyi bir yer.

EDIT2: Örneğimdeki olası bir kafa karışıklığına işaret etti. __init__.pyimport something'da, paketten gerekli olmayan herhangi bir modülü alabilirsiniz. Örneğin, en üst düzeyde test.py ardından, import datetime ile değiştirebilirsiniz Bu snippet'lerde her iki çalışacaktır:

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

ve

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

alt satır: __init__.py atanan tüm isimler, olmak Paketleri veya işlevleri paket içinde içe aktardığınızda, modüllerin, işlevlerin veya sınıfların içe aktarıldığı, paket ad alanında otomatik olarak kullanılabilir.

+0

Tamam, teşekkürler. Ama hala bu sınıfları başlatma kodu olarak düşünmüyorum (ama belki de bu konuda yanlışım) sınıfları eklemek için neden iyi bir fikir olacağını emin değilim. – Erik

+0

Bunlar, her paketle çalışırken her zaman yararlı olan sınıflardır. Ama ben spekülasyon yapmak istemiyorum, orada bulunmanın birçok nedeni olabilir, objektif olsun ya da olmasın :) –

+12

Bu tarihsel nedenlerden dolayı da olabilir. Modülü pakete dönüştürdüğünüzde, module.py modül/__ init__.py modülüne tüm mevcut kodlar daha önce olduğu gibi kullanabilir ancak artık modülün alt modülleri olabilir. –

32

Bu sadece kişisel tercih gerçekten, ve python modüllerinizin düzeni ile ilgili.

erikutils adlı bir modülünüz olduğunu varsayalım. Orada bir modül olabilir iki yolu vardır, ya bir dosya sys.path üzerinde erikutils.py denilen varsa veya adında bir dizin içindeki boş __init__.py dosyası ile sizin sys.path üzerinde erikutils var. O zaman, fileutils, procutils, parseutils adında bir dizi modülünüz olduğunu ve bunların erikutils altında alt modüller olmasını istediğinizi varsayalım. ,

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

Belki fileutils ait olmadığını birkaç işlevi vardır: Yani bazı .py fileutils.py, procutils.py adı verilen dosyaları ve parseutils.py yapmak procutils veya parseutils modülleri.Ve diyelim ki miscutils adında yeni bir modül oluşturmak gibi hissetmiyorsunuz. VE, bunu böyle işlevini çağırmak edebilmek istiyorum: erikutils modül bir dizin, bir dosya değil, çünkü

erikutils.foo() 
erikutils.bar() 

ziyade yapıyor

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

Demek ki tanımlamak zorunda __init__.py dosyasındaki işlevlerdir. django olarak

, Aklıma gelen en iyi örnek django.db.models.fields olduğunu. TÜM Django * Saha sınıfları django/db/modeller/alanlar dizinde __init__.py dosyasında tanımlanır. Sanırım her şeyi bir varsayımsal django/db/models/fields.py modeline tıkmak istemedikleri için yaptıkları için birkaç alt modüle (related.py, files.py, örneğin) ve (kendisi modülü alanlarda yapılan * Alan tanımları sıkışmış bu nedenle, __init__.py). __init__.py dosyasını kullanarak

+1

dgrant, demek istediğim '' '' '' '' '' '' '' dır, dış bir modül olabilir.Yorum için teşekkürler, daha net hale getirmek için gönderimi düzenleyeceğim. –

+0

Harika, teşekkür ederim. – Erik

26

dışarıdan iç paket yapısı görünmez olmasını sağlar. İç yapı değişirse (örneğin bir yağ modülünü ikiye ayırdığınız için), yalnızca __init__.py dosyasını ayarlamalısınız, ancak pakete bağlı olan kodu değiştirmemelisiniz. Paketinizin parçalarını görünmez yapabilirsiniz, ör. Genel kullanıma hazır değillerse. Bunu tipik bir __init__.py gibi görünebilir, del komutunu kullanabilirsiniz

Not: ayrılmaya karar vermesi durumunda Şimdi

from somemodule import some_function1, some_function2, SomeObject 

del somemodule 

somemodule yeni __init__.py olabilir: Dan

from somemodule1 import some_function1, some_function2 
from somemodule2 import SomeObject 

del somemodule1 
del somemodule2 

Dışarısı hala tam olarak önceki gibi görünüyor.

+1

Bir modülü silme amacı nedir? – Arlen

+0

@Arlen: Mesele, bu, kamu API'sinin bir parçası olmamasıdır. Bir modülü yeniden adlandırırsanız, bağımlı kodun kırılmadığından emin olabilirsiniz. Buna ek olarak, API öğelerinin yalnızca bir kez, örneğin otomatik olarak API belgelerini oluşturmak için iç gözlemleme kullanıldığında görünmesini sağlar. – nikow

+4

@Arlen: Bir modülün silinmesi, birisinin doğrudan " .somemodule1" dosyasını içe aktarmasını engeller. Yalnızca '__init __. Py' öğesinde tanımlanmış veya içe aktarılan "" nesnelerini ve silinmemiş alt modülleri içe aktarabilirsiniz. – MestreLion

İlgili konular