मान लीजिए मेरा मॉड्यूल myclass.py है, और यहां कोड है:

#!/usr/bin/env python
# coding=utf-8

class A(object):
    b = B()
    def __init__(self):
        pass

class B(object):
    pass

और इसे आयात करें

In [1]: import myclass
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-1-e891426834ac> in <module>()
----> 1 import myclass

/home/python/myclass.py in <module>()
      2 # coding=utf-8
      3 
----> 4 class A(object):
      5     b = B()
      6     def __init__(self):

/home/python/myclass.py in A()
      3 
      4 class A(object):
----> 5     b = B()
      6     def __init__(self):
      7         pass

NameError: name 'B' is not defined

मुझे पता है कि अगर मैं कक्षा ए के ऊपर कक्षा बी को परिभाषित करता हूं, तो ठीक है, कोई त्रुटि नहीं है। लेकिन, मैं ऐसा नहीं करना चाहता, क्या इसे हल करने के लिए कोई अन्य तरीके हैं। और मुझे पता है कि सी में फंक्शन डिक्लेरेशन होता है।धन्यवाद!

2
GoingMyWay 17 अगस्त 2016, 09:27

3 जवाब

सबसे बढ़िया उत्तर

वर्ग परिभाषा एक बयान है। जब कथन AA निष्पादित किया जाता है, BB का कथन अभी तक निष्पादित नहीं होता है। इसलिए, अभी तक कोई वर्ग B नहीं है और आपको NameError: name 'B' is not defined मिलता है

class A(object):
    b = B()              # <== AA
    def __init__(self):
        pass
class B(object):         # <== BB
    pass

ठीक करना:


आप कक्षाओं का क्रम बदल सकते हैं:

class B(object):
    pass

class A(object):
    b = B()
    def __init__(self):
        pass

आप B वर्ग का उपयोग करने वाले कथन को classmethod में स्थानांतरित कर सकते हैं और इसे कक्षा B की परिभाषा के बाद कॉल कर सकते हैं:

class A(object):

    @classmethod
    def init(cls):
        cls.b = B()

    def __init__(self):
        pass

class B(object):
    pass

A.init()
8
napuzba 17 अगस्त 2016, 09:47

यदि आप इसे ऐसा करते हैं तो इसे काम करना चाहिए:

class A(object): 
    def __init__(self): 
        self.b = B() 

class B(object): 
    pass

संपादित करें: आप इसे इस तरह कर सकते हैं यदि आप कक्षा ए लिखने के बाद कक्षा की सभी परिभाषाएं लिखना चाहते हैं।

class B:
    pass

class A(object): 
    b = B()
    def __init__(self): 
        pass 

class B(object): 
    def __init__(self):
        pass

संपादित करें 2: उपरोक्त समाधान पर ध्यान न दें, यह काम नहीं करता है।

0
Shubham Vasaikar 17 अगस्त 2016, 11:42

क्या आप जो कर रहे हैं उसे करने का कोई अच्छा कारण है? सामान्य तौर पर यह पायथन में काफी खतरनाक पैटर्न है।

आपके मामले में

class A(object):
    b = B()
    def __init__(self):
        pass

आप कक्षा ए के लिए बी का एक उदाहरण बाध्य कर रहे हैं, जिसका अर्थ है कि कक्षा ए का प्रत्येक उदाहरण कक्षा बी के समान उदाहरण को साझा करेगा। यह एक ऐसा मामला है जिसे आपको ठीक से संभालना होगा।

आम तौर पर आप यह नहीं चाहते हैं, यदि आप चाहते हैं कि ए का प्रत्येक उदाहरण बी के उदाहरण से संबंधित हो, तो आपको __init__ के अंदर असाइनमेंट करना होगा।

class A(object): 
    def __init__(self): 
        self.b = B() 

इन मामलों में यह मीटर नहीं है जहां कक्षा बी परिभाषित की गई है, क्योंकि यह रन टाइम पर तत्काल है।

फिर से सावधान रहें कि दो मामलों में शब्दार्थ बहुत अलग है (यदि आप जावा को जानते हैं, तो पूर्व एक static विशेषता को परिभाषित करने जैसा है)।

के बारे में:

और मुझे पता है कि सी में, समारोह घोषणा है

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

पायथन एक व्याख्या की गई भाषा है, जिसका मूल रूप से अर्थ यह है कि प्रत्येक कथन अनुवादित है जब इसे कहा जाता है और जब मॉड्यूल आयात किया जाता है तो कक्षा घोषणा को कॉल किया जाता है।

तो संक्षेप में: यदि आपको वास्तव में कक्षा बाध्य उदाहरण की आवश्यकता है, तो आपको कक्षा ए से पहले कक्षा बी घोषित करना होगा, अन्यथा आपको __init__ के अंदर बी को तत्काल करना होगा, फिर आप जहां चाहें बी घोषित कर सकते हैं (चूंकि इसे रनटाइम पर कहा जाता है)।

0
Oberix 17 अगस्त 2016, 12:54