2012-06-27 13 views
33

कोडअजगर चर संदर्भ काम

y = 7 
x = y  
x = 8 

अब में, y 7 हो जाएगा और एक्स 8. हो जाएगा लेकिन असल में मैं परिवर्तन y चाहता हूँ। क्या मैं y का संदर्भ असाइन कर सकता हूं और ऐसा कर सकता हूं?

उदाहरण के लिए, C++ एक ही बात के रूप में प्राप्त किया जा सकता,

int y = 8; 
int &x = y; 
x = 9; 

अब दोनों y & एक्स हो जाएगा 9

उत्तर

44

नहीं, आप नहीं कर सकते हैं। जैसा कि अन्य उत्तर बताते हैं, आप (एबी?) एक समान प्रभाव प्राप्त करने के लिए उत्परिवर्तनीय वस्तुओं के एलियासिंग का उपयोग कर सकते हैं। हालांकि, यह सी ++ संदर्भों के समान नहीं है, और मैं समझाना चाहता हूं कि वास्तव में किसी भी गलतफहमी से बचने के लिए क्या होता है।

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

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

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

क्या यह एक अधिक प्रतिबंधक मॉडल है? शायद, लेकिन यह काफी समय के लिए पर्याप्त शक्तिशाली है। और जब ऐसा नहीं होता है, तो आप इसके चारों ओर काम कर सकते हैं, या तो नीचे दिए गए एक कस्टम वर्ग के साथ, या (समकक्ष, लेकिन कम स्पष्ट) एकल तत्व संग्रह।

class Reference: 
    def __init__(self, val): 
     self._value = val # just refers to val, no copy 

    def get(self): 
     return self._value 

    def set(self, val): 
     self._value = val 

कि अभी भी आप एक "नियमित" चर या वस्तु क्षेत्र अन्य नाम पर अनुमति नहीं दी जाएगी, लेकिन आप एक ही Reference वस्तु (परिवर्तनशील-सिंगलटन-संग्रह विकल्प के लिए डिट्टो) की चर्चा करते हुए कई चर हो सकता है। आपको हमेशा .get()/.set() (या [0]) का उपयोग करने के लिए सावधान रहना होगा।

+2

अच्छा स्पष्टीकरण, यह स्पष्ट करने के लिए +1 कि इसमें उत्परिवर्तन के साथ कुछ भी नहीं है। –

11

नहीं है, अजगर इस सुविधा नहीं है।

आप एक सूची था (या किसी अन्य परिवर्तनशील वस्तु) आप उद्देश्य यह है कि दोनों x और y के लिए बाध्य कर रहे हैं परिवर्तनशील द्वारा तुम क्या चाहते हो सकता है:

>>> x = [7] 
>>> y = x 
>>> y[0] = 8 
>>> print x 
[8] 

ऑनलाइन काम कर यह देखें: ideone

+1

हालांकि यह वास्तव में सहायक है हालांकि एक साधारण संख्यात्मक मूल्य के इस "उत्परिवर्तन" में कम या ज्यादा नकारात्मक गिरावट है। एक तत्व के साथ एक सूची में पूर्णांक को चालू करने के लिए आपको सामान्य रूप से आवश्यक स्मृति स्थान से 3 गुना अधिक आवश्यकता होती है। उदाहरण (मैं आकार-अंतर को चित्रित करने के लिए sys.getsizeof (...) का उपयोग करूंगा): x = 1 -> sys.getsizeof (x) -> हमें 14 -> x = [1] -> sys.getsizeof (x) -> हमें 36 – rbaleksandar

5

आपको इसके लिए एक म्यूटेबल ऑब्जेक्ट का उपयोग करना चाहिए।

अजगर x & y में सिर्फ वस्तुओं के लिए संदर्भ तो y = 7 वस्तु 7 करने के लिए y अंक का मतलब है। x=y7 को x भी अंक का मतलब है, लेकिन जैसा कि 7 अपरिवर्तनीय है तो एक्स का मान बदल रहा है बस वस्तु 7 और y अभी भी 7 की ओर इशारा करते रहता है बदल जाता है।

>>> y = [7] 
>>> x = y 
>>> x[0] = 8 # here you're changing [7] not x or y, x & y are just references to [7] 
>>> y 
[8] 
+0

देता है, आप यह इंगित करना चाहते थे कि वाई एक्स बदलने के बाद भी अपरिवर्तित बनी हुई है, लेकिन यह वह नहीं है जिसे आपने यहां लिखा था। कृपया स्पष्ट करें। –

1

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

class Value(object): 
    def __init__(self, value): self.value = value 

y = Value(7) 
x = y 
x.value = 8 
print y.value 

ideone

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