2009-02-07 7 views
22

मेरे पास एक फ़ाइल में पायथन कक्षाओं की एक श्रृंखला है। कुछ वर्ग दूसरों का संदर्भ देते हैं।क्या पाइथन में कक्षा प्रोटोटाइप (या आगे की घोषणाएं) हैं?

class A(): 
    pass 

class B(): 
    c = C() 

class C(): 
    pass 

कि चलाने के लिए कोशिश कर रहा है, मैं NameError: name 'C' is not defined मिलती है:

मेरे कोड कुछ इस तरह है। काफी उचित है, लेकिन क्या इसे काम करने का कोई तरीका है, या क्या मुझे अपनी कक्षाओं को मैन्युअल रूप से समायोजित करने के लिए फिर से आदेश देना है? सी ++ में, मैं एक वर्ग प्रोटोटाइप बना सकता हूं। क्या पाइथन समकक्ष है?

(मैं वास्तव में Django मॉडल के साथ खेल रहा हूं, लेकिन मैंने मामलों को जटिल नहीं करने की कोशिश की)।

+0

एफडब्ल्यूआईडब्ल्यू, इसे http://en.wikipedia.org/wiki/Forward_declaration कहा जाता है, प्रोटोटाइप नहीं (http://en.wikipedia.org/wiki/Prototype-based_programming)। – Constantin

+0

इसे कर्निघान और रिची में फ़ंक्शन प्रोटोटाइप कहा जाता है, जहां मुझे इसे याद है। – Mat

+0

बस मेरी के एंड आर प्रतिलिपि में "कक्षा प्रोटोटाइप" की जांच नहीं की गई;) – Constantin

उत्तर

31

पायथन में आप प्रति प्रोटोटाइप नहीं बनाते हैं, लेकिन आपको "कक्षा विशेषताओं" और उदाहरण-स्तर विशेषताओं के बीच अंतर को समझने की आवश्यकता है। उदाहरण में आपने ऊपर दिखाया है, आप कक्षा बी पर कक्षा विशेषता घोषित कर रहे हैं, उदाहरण-स्तर विशेषता नहीं।

यह आप के लिए क्या देख रहे है:

class B(): 
    def __init__(self): 
     self.c = C() 
+1

मैं एक स्पष्टीकरण के लिए उत्सुक हूं कि क्यों पाइथन सी के def'n पा सकते हैं जब यह एक आवृत्ति विशेषता असाइन कर रहा है लेकिन कक्षा स्तर एक नहीं है। क्या ऐसा इसलिए है क्योंकि यह रनटाइम की बजाय कक्षा परिभाषा पर असाइनमेंट करने की कोशिश कर रहा है? – Dana

+1

हां, चूंकि सी = सी() कक्षा परिभाषा (मॉड्यूल लोड पर निष्पादित) में है, कक्षा सी अभी तक मौजूद नहीं है। – truppo

+1

@truppo सही है। जब आप क्लास गुणों की घोषणा करते हैं तो मॉड्यूल लोड होने पर संबंधित संदर्भ हल किए जाते हैं (यानी कक्षा का अर्थ है)। __init__ विधि अन्य भाषाओं में रचनाकारों के समान है, इसलिए इसके स्थानीय दायरे में संदर्भों को तब तक हल करने की आवश्यकता नहीं है जब तक –

6

यह आपकी समस्या का समाधान होगा के रूप में प्रस्तुत (लेकिन मुझे लगता है कि आप वास्तव में के रूप में jholloway7 प्रतिक्रिया व्यक्त की एक उदाहरण विशेषता के लिए देख रहे हैं):

class A: 
    pass 

class B: 
    pass 

class C: 
    pass 

B.c = C() 
+1

Django मॉडल के मामले में, यह एकमात्र उत्तर है जो काम करता है क्योंकि हम कक्षा को संशोधित करने की कोशिश कर रहे हैं, कक्षा के उदाहरण नहीं। Django कक्षाओं introspect और उस ओआरएम परत ड्राइव करने के लिए मेटाडेटा का उपयोग करता है। – verveguy

+0

मैंने अपनी टिप्पणी वापस ले ली - यह आगे की घोषणाओं के बिना एक पाइथन कक्षा में कक्षा के सदस्यों को जोड़ने का एक तरीका है। लेकिन यह Django मॉडल घोषणाओं के लिए वास्तव में समस्या को हल नहीं करता है (डी) डीजेगो इन मॉडलों को संसाधित करने के तरीके के अंदर आंतरिक है। – verveguy

0

कक्षा बनाम उदाहरण विशेषताओं के बारे में सभी सही जवाब। हालांकि, आपके पास त्रुटि होने का कारण सिर्फ आपकी कक्षाओं को परिभाषित करने का आदेश है। बेशक कक्षा सी को अभी तक परिभाषित नहीं किया गया है (क्योंकि कक्षा-स्तर कोड आयात पर तुरंत निष्पादित किया जाता है):

class A(): 
    pass 

class C(): 
    pass 

class B(): 
    c = C() 

काम करेगा।

+1

मुझे पता है कि मैं इसे ठीक करने के लिए कर सकता हूं (और जो मैंने अभी किया है) लेकिन अब मेरा कोड ऑर्डरिंग गैर-सहज है। – Mat

+0

ठीक है, मैं देखता हूं कि आपका क्या मतलब है, लेकिन मुझे लगता है कि यह ऐसा कुछ भी उपयोग करने की कोशिश करने के लिए अधिक सहज नहीं होगा जो अभी तक मौजूद नहीं है। ऐसा करने की तरह: प्रिंट करें; ए = 5 –

+1

कुछ कथन चलाने की कोशिश कर रहा है जैसे प्रिंट ए; ए = 5 स्पष्ट रूप से ज्यादा समझ में नहीं आता है, लेकिन सी-शैली वर्ग प्रोटोटाइप उपलब्ध होने पर एक वर्ग स्वयं निहित और संदर्भ को आगे बढ़ाने के लिए पूरी तरह से उचित है। – Mat

3

पायथन में प्रोटोटाइप या रूबी-स्टाइल ओपन क्लासेस नहीं हैं। लेकिन अगर आपको वास्तव में उनकी ज़रूरत है, तो आप एक मेटाक्लास लिख सकते हैं जो नया ओवरलोड करता है ताकि यह मौजूदा नामस्थान में एक लुकअप कर सके कि यह देखने के लिए कि कक्षा पहले से मौजूद है या नहीं, और यदि यह एक नया निर्माण करने के बजाय मौजूदा प्रकार ऑब्जेक्ट देता है । मैंने ओआरएम पर ऐसा कुछ किया है, मैं थोड़ी देर पहले लिखता हूं और यह बहुत अच्छा काम करता है।

+0

उत्तर नहीं है, लेकिन अजीब है, क्या आप अपने समाधान का उदाहरण दे सकते हैं? जब बी पर निर्भर करता है, बी सी पर निर्भर करता है और सी पर निर्भर करता है। –

40

दरअसल, उपर्युक्त सभी पाइथन के बारे में महान अवलोकन हैं, लेकिन उनमें से कोई भी आपकी समस्या का समाधान नहीं करेगा।

Django को आत्मनिरीक्षण सामग्री की आवश्यकता है।

class Car(models.Model): 
    manufacturer = models.ForeignKey('Manufacturer') 
    # ... 

class Manufacturer(models.Model): 
    # ... 

नोट एक स्ट्रिंग बजाय शाब्दिक वर्ग संदर्भ के रूप में वर्ग के नाम के उपयोग:

सही जिस तरह से आप क्या चाहते करने के लिए निम्नलिखित है। Django इस समस्या को ठीक से निपटने के लिए प्रदान करता है कि पायथन आगे की घोषणाएं प्रदान नहीं करता है।

यह प्रश्न मुझे क्लासिक समर्थन प्रश्न की याद दिलाता है कि आपको किसी भी ग्राहक को किसी समस्या के साथ हमेशा पूछना चाहिए: "आप वास्तव में क्या करने की कोशिश कर रहे हैं?"

+1

यह सवाल स्पष्ट था कि ओपी क्या करने की कोशिश कर रहा था, यह डीजेगो से संबंधित था और ओपी ऑब्जेक्ट उन्मुख प्रोग्रामिंग के लिए पाइथन के मॉडल को समझने की कोशिश कर रहा था, क्योंकि डीजेगो का ओआरएम शुरुआती लोगों के लिए भ्रमित हो सकता है। –

+0

यह सच हो सकता है, लेकिन ओपी समाप्त हो गया सवाल पूछने के शीर्षक से बहुत अलग था। मैं तीन साल बाद शीर्षक बदलने के लिए अनिच्छुक हूं, भले ही यह गलत है। – ObscureRobot

+0

धन्यवाद! यह वह सही समस्या है जिसमें मैं शामिल हो रहा था। – Lander

संबंधित मुद्दे