2012-06-26 15 views
6

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

>>> 
X attributes: 

60 
Bar 
Y attributes: 

60 
Bar 
>>> 

मुझे लगता है यह कह रही किया जाना चाहिए::

X attributes: 

20 
Foo 
Y attributes: 

60 
Bar 

क्या मैं गलत कर रहा हूँ

class exampleClass(object): 

    attribute1=0 
    attribute2="string" 

x=exampleClass 
x.attribute1=20 
x.attribute2="Foo" 

y=exampleClass 
y.attribute1=60 
y.attribute2="Bar" 

print("X attributes: \n") 
print(x.attribute1) 
print(x.attribute2) 

print("Y attributes: \n") 
print(y.attribute1) 
print(y.attribute2) 

यहाँ कार्यक्रम मेरे कंसोल से बाहर आने की तरह लग रहा है?

+0

संक्षिप्त उत्तर: 'x' और 'y' दोनों क्लास ऑब्जेक्ट' exampleClass' को संदर्भित करते हैं, इसके उदाहरण नहीं। उदाहरण बनाने के लिए, आपको क्लास ऑब्जेक्ट को 'x = exampleClass()' में कॉल करने की आवश्यकता है। बाद में आपके द्वारा 'x' में किए गए परिवर्तनों को केवल उस उदाहरण को प्रभावित किया जाएगा जो इसका संदर्भ देता है। – martineau

उत्तर

8

आप क्लास विशेषताओं को बना रहे हैं, जब आप आवृत्ति विशेषताओं को चाहते हैं। इस का उपयोग करें:

class exampleClass(object): 
    def __init__(self): 
     self.attribute1 = 0 
     self.attribute2 = "string" 

इसके अलावा, आप exampleClass से किसी उदाहरण की रचना नहीं करते हैं, तो आप इस की जरूरत है:

x = exampleClass() 
y = exampleClass() 

आपका कोड बस वर्ग के लिए नए नाम का उपयोग कर रहा है, और उसके गुण बदल रहा है।

+0

यह मेरे कंसोल में ऐसा लगता है ... अभी भी एक ही समस्या का सामना कर रहा है। >>> वर्ग exObj (वस्तु): \t डीईएफ़ __init __ (स्वयं): \t \t self.attribute1 = 0 \t \t self.attribute2 = "string" \t \t >>> ce = exObj > >> सीटी = exObj >>> ce.attribute1 = 44 >>> ct.attribute1 = 54 >>> ce.attribute1 >>> ct.attribute1 >>> – jecaklafa

+0

किसी न किसी के लिए खेद है स्वरूपण। – jecaklafa

+0

@jecaklafa: आपको कक्षाओं को माता-पिता के साथ तत्काल करने की आवश्यकता है। –

3

संशोधित किए गए तो यह स्पष्ट है।

कोड है कि आप के साथ

, तो अपनी समस्या यह है कि आप चर x बना रहे हैं और y बल्कि वस्तुओं विश्वास जो अब मैं सभी चर्चा और पदों के साथ इस मुद्दे के रूप में सामने आए instantiating से वर्ग परिभाषा का उल्लेख है।

x = exampleClass 

अब इसका मतलब है कि एक्स अब वर्ग परिभाषा को इंगित करता है। क्योंकि जब से तुम exampleClass की एक चर के रूप में attribute1 है, तो आप ऐसा कर सकते हैं यह दिलचस्प है:

x.attribute1 = 3 

अब आप निम्नलिखित दिए थे:

exampleClass.attribute1 

इसके बजाय 0 देखकर जैसा कि आप मूल रूप से यह सेट की, अब आप 3 देखेंगे! वर्ग के

का दृष्टांत करने के लिए वस्तुओं आप निम्न कार्य करने होंगे:

x.attribute1 = 219 
फिर

:

x = exampleClass() 
y = exampleClass() 

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

मैं सुझाव है कि आप नेड Batchelder का जवाब हालांकि (और अब अन्य) को पढ़ने के रूप में आप के साथ init समारोह है कि रास्ते में उदाहरण चर बनाने जाना चाहिए के रूप में यह अधिक स्वच्छ और डिजाइन मानकों है कि ज्यादातर पालन की ओर अधिक है।

लेकिन ऑब्जेक्ट क्लास से प्राप्त होने के बाद से कुल मिलाकर आप यह मान सकते हैं कि इस तरह से उदाहरण (कोष्ठक के साथ) और इस तरह से आप ऑब्जेक्ट वैल्यू को संशोधित कर सकते हैं क्योंकि मुझे लगता है कि उन्हें उदाहरण के चर के बिना भी " स्व "।

4

आपने गुण क्लास विशेषताओं को बनाया है। इसका मतलब यह है कि वे वर्ग की वस्तुओं के लिए कक्षा में ही नहीं हैं।

आप वस्तु देखते हुए आप की तरह कुछ कर सकते हैं चाहते हैं:

class exampleClass(object): 
     def __init__(self): 
      self.attribute1=0 
      self.attribute2="string" 

x = exampleClass() 
y = exampleClass() 

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

+2

अभी भी उदाहरण क्लास के बजाय exampleClass() करने की आवश्यकता है अन्यथा यह उस वर्ग के ब्लूप्रिंट के लिए एक सूचक होगा। – richardhsu

+0

@richardhsu: यह 'NameError' उत्पन्न करेगा क्योंकि विशेषताएँ अभी तक नहीं बनाई गई हैं। –

+1

बिल्कुल, लेकिन आप अभी भी x = exampleClass कर सकते हैं, यह पायथन में मान्य है और x को उदाहरण क्लास का संदर्भ देता है, इसलिए हाँ आपका कोड कक्षा के डिज़ाइन के लिए सही है लेकिन उस वर्ग के किसी ऑब्जेक्ट को तत्काल करने के लिए कोष्ठक की आवश्यकता होती है। – richardhsu

1

कक्षाएं भी पाइथन में ऑब्जेक्ट्स हैं। इसलिए, उन्हें चर के लिए असाइन किया जा सकता है और उनके स्वयं के गुण होते हैं, जैसा कि किसी भी अन्य वस्तु के समान होता है।

class ब्लॉक में आपके द्वारा बनाए गए सभी नाम बनाए गए वर्ग के गुण बन जाते हैं। वे उस कक्षा के भविष्य के उदाहरणों के गुण हैं। लेकिन जब आप किसी उदाहरण से एक विशेषता को पढ़ने का प्रयास करते हैं और उदाहरण में उस विशेषता नहीं होती है, तो पायथन इंस्टॉलेशन के क्लास 'विशेषताओं को देखने के लिए डिफ़ॉल्ट होता है, और यदि उसे कोई मिलता है तो उसे वापस कर देगा। वास्तव में पाइथन में विधियां कैसे काम करती हैं; वे कक्षा में केवल गुण हैं, और जब आप उन्हें उदाहरण से पुनर्प्राप्त करने का प्रयास करते हैं (जहां वे मौजूद नहीं हैं) वे कक्षा को देखकर पाए जाते हैं।

इस बात को ध्यान में रखते हुए, आपका प्रोग्राम ऐसा नहीं करता जो आपको लगता है।

class exampleClass(object): 

    attribute1=0 
    attribute2="string" 

यहाँ आप दो विशेषताओं attribute1 और attribute2 के साथ एक कक्षा exampleClass नाम है, बना लिया है। वे उदाहरण विशेषताओं हैं; यह पाइथन सीखने वाले लोगों की वास्तव में एक आम गलती है। आपको इसे स्वयं से प्रशिक्षित करने की ज़रूरत है, क्योंकि सरल उदाहरणों के लिए यह अक्सर "जैसे" काम करने लगता है, वे उदाहरण गुण थे। class ब्लॉक में बाध्यकारी नाम क्लास ऑब्जेक्ट पर गुण बनाता है। उदाहरण विशेषताओं को बनाने का एकमात्र तरीका यह है कि उदाहरण के बाद उदाहरण का संदर्भ प्राप्त करें और उस पर विशेषताओं को असाइन करें; पाइथन आपको यह करने के लिए स्थान के रूप में __init__ विधि (जिसे इंस्टेंस बनाया जाता है) कहा जाता है।

तो अंगूठे का मूल नियम यह है: कक्षा ब्लॉक में परिभाषित नाम क्लास ऑब्जेक्ट पर गुण हैं, के गुणों के रूप में निर्दिष्ट नाम __init__ उस वर्ग के सभी उदाहरणों पर गुण हैं।

आपका भ्रम आगे एक और मुद्दा का संयोजन होता है:

x=exampleClass 
x.attribute1=20 
x.attribute2="Foo" 

क्योंकि कक्षाएं अजगर में सब कुछ की तरह वस्तुओं, इस पूरी तरह से उचित अजगर कोड है कर रहे हैं, लेकिन यह आप क्या सोचते हैं यह करता है नहीं करता है। आपने वास्तव में अपनी कक्षा का उदाहरण नहीं बनाया है; इसके लिए आपको कक्षा को exampleClass() में कॉल करने की आवश्यकता है। नंगे नाम exampleClass बस क्लास ऑब्जेक्ट को संदर्भित करता है, इसलिए आपने उस ऑब्जेक्ट पर x नाम को बाध्य कर दिया है और फिर इसके कुछ विशेषताओं को असाइन किया है। स्वाभाविक रूप से, जब आप क्लास ऑब्जेक्ट पर y को बाध्य करते हैं और y के माध्यम से उस ऑब्जेक्ट पर विशेषताओं को असाइन करते हैं, तो x द्वारा निर्दिष्ट ऑब्जेक्ट प्रभावित होता है (यह वही ऑब्जेक्ट है)।

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