2008-09-23 15 views
75

पर कोड जोड़ना मैं देख रहा हूं कि django में मॉडल सिस्टम कैसे काम करता है और मैंने कुछ ऐसा देखा जो मुझे समझ में नहीं आया।__init__.py

मुझे पता है कि आप एक खाली __init__.py फ़ाइल बनाते हैं ताकि यह निर्दिष्ट किया जा सके कि वर्तमान निर्देशिका एक पैकेज है। और आप __init__.py में कुछ चर सेट कर सकते हैं ताकि आयात * ठीक से काम करता हो।

लेकिन django से एक गुच्छा जोड़ता है ... आयात ... कथन और __init__.py में कक्षाओं का एक गुच्छा परिभाषित करता है। क्यूं कर? क्या यह सिर्फ चीजों को गन्दा दिखता है? क्या ऐसा कोई कारण है जिसके लिए __init__.py में इस कोड की आवश्यकता है?

+13

यह वास्तव में Django के बारे में नहीं है? हां, आपने इसे पहले Django में देखा, लेकिन यह एक शुद्ध पायथन चीज़ की तरह लगता है - शायद Django टैग वास्तव में उपयुक्त नहीं है। –

+0

मुझे '__init __। Py' django 1.8 में कोई आयात विवरण नहीं दिखाई देता है। क्या यह एक पुराने संस्करण के लिए था? यदि ऐसा है तो कौन सा संस्करण? –

उत्तर

67

__init__.py में सभी आयात उपलब्ध कराए जाते हैं जब आप पैकेज (निर्देशिका) को आयात करते हैं।

उदाहरण:

./dir/__init__.py:

import something 

./test.py:

import dir 
# can now use dir.something 

संपादित करें: उल्लेख करना भूल गया, __init__.py में कोड पहली बार जब आप उस निर्देशिका से किसी भी मॉड्यूल आयात चलाता है। तो यह आमतौर पर किसी पैकेज-स्तर प्रारंभिक कोड को रखने के लिए एक अच्छी जगह है।

EDIT2: ड्रिगेंट ने मेरे उदाहरण में संभावित भ्रम की ओर इशारा किया। __init__.pyimport something पैकेज से आवश्यक कोई भी मॉड्यूल आयात नहीं कर सकता है। उदाहरण के लिए, हम इसे import datetime साथ, तो हमारे शीर्ष स्तर test.py में जगह ले सकता है इन स्निपेट के दोनों काम करेगा:

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

और

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

लब्बोलुआब यह है: __init__.py में सौंपा सभी के नाम, हो जब भी आप पैकेज में पैकेज या मॉड्यूल आयात करते हैं, तो यह मॉड्यूल, फ़ंक्शंस या क्लासेस आयात करता है, पैकेज नामस्थान में स्वचालित रूप से उपलब्ध होता है।

+0

ठीक है, धन्यवाद। लेकिन मुझे अभी भी यकीन नहीं है कि कक्षाओं को '__init __। Py 'में जोड़ने का अच्छा विचार क्यों होगा, मैं वास्तव में इन कक्षाओं के आरंभिक कोड पर विचार नहीं करता (लेकिन शायद मैं इसके बारे में गलत हूं)। – Erik

+0

ये संभवतः कक्षाएं हैं जो हर बार पैकेज के साथ काम करते समय उपयोगी होती हैं। लेकिन मैं अनुमान लगा नहीं चाहता हूं, वहां कई कारण हो सकते हैं कि वे वहां क्यों हैं, उद्देश्य या नहीं :) –

+12

यह ऐतिहासिक कारणों से भी हो सकता है। जब आप मॉड्यूल को पैकेज में कनवर्ट कर रहे हैं, मॉड्यूल/__ init__.py के लिए module.py.py सभी मौजूदा कोड इसे पहले के रूप में उपयोग कर सकते हैं लेकिन अब मॉड्यूल में सबमिड्यूल हो सकते हैं। –

32

यह वास्तव में व्यक्तिगत प्राथमिकता है, और आपके पायथन मॉड्यूल के लेआउट के साथ करना है।

मान लें कि आपके पास erikutils नामक एक मॉड्यूल है। दो तरीके है कि यह एक मॉड्यूल हो सकता है, या तो आप एक फ़ाइल अपने sys.path पर erikutils.py कहा जाता है या आप एक निर्देशिका कहा जाता है इसके अंदर एक खाली __init__.py फ़ाइल के साथ अपने sys.path पर erikutils है। तो मान लें कि आपके पास fileutils, procutils, parseutils नामक मॉड्यूल का एक गुच्छा है और आप चाहते हैं कि वे erikutils के अंतर्गत उप-मॉड्यूल हों। तो अगर आप कुछ .py fileutils.py, procutils.py बुलाया फ़ाइलें, और parseutils.py बनाने:

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

हो सकता है कि आप कुछ कार्यों कि सिर्फ fileutils में संबंधित नहीं है, procutils, या parseutils मॉड्यूल।और मान लीजिए कि आप miscutils नामक एक नया मॉड्यूल बनाने की तरह महसूस नहीं करते हैं। और, यदि आप ऐसा तरह समारोह कॉल करने के लिए सक्षम होने के लिए करना चाहते हैं:

erikutils.foo() 
erikutils.bar() 

बजाय कर

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

तो क्योंकि erikutils मॉड्यूल एक निर्देशिका, नहीं एक फाइल है, हम को परिभाषित करने के लिए है यह __init__.py फ़ाइल के अंदर कार्य करता है।

django में, सबसे अच्छा उदाहरण मैं सोच सकता हूं django.db.models.fields है। सभी django * फ़ील्ड क्लासेस __init__.py फ़ाइल django/db/मॉडल/फ़ील्ड निर्देशिका में परिभाषित हैं। मुझे लगता है कि उन्होंने ऐसा इसलिए किया क्योंकि वे सब कुछ एक hypothetical django/db/models/field.py मॉडल में क्रैम नहीं करना चाहते थे, इसलिए उन्होंने इसे कुछ सबोडोड्यूल में विभाजित किया (संबंधित.py, files.py, उदाहरण के लिए) और उन्होंने फ़ील्ड मॉड्यूल में बनाई गई * फ़ील्ड परिभाषाओं को फंस गया (इसलिए, __init__.py)।

+1

ड्रेगेंट, मेरा मतलब यह था कि 'कुछ' बाहरी मॉड्यूल हो सकता है, dir.something काम करेगा।टिप्पणी के लिए धन्यवाद, मैं इसे और अधिक स्पष्ट करने के लिए अपनी पोस्ट संपादित कर दूंगा। –

+0

ग्रेट, धन्यवाद ड्रेगेंट। – Erik

26

__init__.py फ़ाइल का उपयोग करके आप आंतरिक पैकेज संरचना को बाहर से अदृश्य बना सकते हैं। यदि आंतरिक संरचना बदलती है (उदा। क्योंकि आप एक वसा मॉड्यूल को दो में विभाजित करते हैं) तो आपको केवल __init__.py फ़ाइल को समायोजित करना होगा, लेकिन पैकेज पर निर्भर कोड नहीं है। आप अपने पैकेज के कुछ हिस्सों को अदृश्य भी बना सकते हैं, उदा। अगर वे सामान्य उपयोग के लिए तैयार नहीं हैं।

ध्यान दें कि आप del आदेश का उपयोग कर सकते हैं, तो एक ठेठ __init__.py कुछ ऐसा दिखाई देगा: अब

from somemodule import some_function1, some_function2, SomeObject 

del somemodule 

अगर आप विभाजित करने का फैसला somemodule नई __init__.py हो सकता है:

from somemodule1 import some_function1, some_function2 
from somemodule2 import SomeObject 

del somemodule1 
del somemodule2 

से पैकेज के बाहर अभी भी बिल्कुल पहले जैसा दिखता है।

+1

मॉड्यूल हटाने का क्या मतलब है? – Arlen

+0

@Allen: बिंदु यह है कि यह सार्वजनिक एपीआई का हिस्सा नहीं है। यदि आप एक मॉड्यूल का नाम बदलते हैं तो आप सुनिश्चित कर सकते हैं कि कोई निर्भर कोड ब्रेक नहीं है। इसके अतिरिक्त यह सुनिश्चित करता है कि एपीआई तत्व केवल एक बार दिखाई देते हैं, उदाहरण के लिए, जब आत्मनिरीक्षण स्वचालित रूप से API दस्तावेज़ बनाने के लिए उपयोग किया जाता है। – nikow

+4

@Allen: मॉड्यूल को हटाने से 'आयात .somemodule1' से सीधे आयात होता है। आप केवल '' से आयात या आयात किए गए ऑब्जेक्ट्स को '__init __। Py', और गैर-हटाए गए submodules में आयात कर सकते हैं। – MestreLion