2013-05-09 3 views
5

पायथन का उपयोग करना, किसी संदर्भ के संदर्भ को संग्रहीत करने का कोई तरीका है, ताकि मैं उस संदर्भ को संदर्भित कर सकूं जो संदर्भ किसी अन्य संदर्भ में संदर्भित करता है?पायथन में एक संदर्भ के संदर्भ को संग्रहीत करना?

class Foo: 
    def __init__(self): 
     self.standalone = 3 
     self.lst = [4, 5, 6] 

मैं कुछ निम्नलिखित के अनुरूप बनाने के लिए चाहते हैं: उदाहरण के लिए, मैं निम्नलिखित वर्ग है लगता है

class Reassigner: 
    def __init__(self, target): 
     self.target = target 
    def reassign(self, value): 
     # not sure what to do here, but reassigns the reference given by target to value 

इस तरह की है कि निम्नलिखित कोड

f = Foo() 
rStandalone = Reassigner(f.standalone) # presumably this syntax might change 
rIndex = Reassigner(f.lst[1]) 
rStandalone.reassign(7) 
rIndex.reassign(9) 

में परिणाम होगा f.standalone7 और f.lst के बराबर [4, 9, 6] के बराबर।

अनिवार्य रूप से, यह पॉइंटर-टू-पॉइंटर के लिए एक एनालॉग होगा।

+0

मुझे लगता है कि संदर्भों का पूरा बिंदु यह है कि आपको बस ऐसा करने में सक्षम नहीं होना चाहिए । –

+0

आप इसका उपयोग कैसे करना चाहते हैं? – FogleBird

+2

यदि आप सी ++ चाहते हैं, तो आप जानते हैं कि इसे कहां मिलना है ... – pydsigner

उत्तर

5

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

class AttributeReassigner: 
    def __init__(self, obj, attr): 
     # use your imagination 
    def reassign(self, val): 
     setattr(self.obj, self.attr, val) 

class ItemReassigner: 
    def __init__(self, obj, key): 
     # use your imagination 
    def reassign(self, val): 
     self.obj[self.key] = val 

f = Foo() 
rStandalone = AttributeReassigner(f, 'standalone') 
rIndex = ItemReassigner(f.lst, 1) 
rStandalone.reassign(7) 
rIndex.reassign(9) 

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

मैंने वास्तव में कुछ बहुत समान उपयोग किया है, लेकिन वैध उपयोग के मामले कुछ और बहुत दूर हैं।

2

सरल उत्तर: आप नहीं कर सकते।
जटिल उत्तर: आप लैम्बडा का उपयोग कर सकते हैं। की तरह।

class Reassigner: 
    def __init__(self, target): 
     self.reassign = target 

f = Foo() 
rIndex = Reassigner(lambda value: f.lst.__setitem__(1, value)) 
rStandalone = Reassigner(lambda value: setattr(f, 'strandalone', value)) 
rF = Reassigner(lambda value: locals().__setitem__('f', value) 
+0

क्यों '__setitem__' और केवल '[]' के साथ सीधे आइटम पहुंच नहीं है? – Eric

+1

दुह, क्योंकि वह एक लैम्ब्डा नहीं है – Eric

+2

जैसा कि एरिक ने महसूस किया है :), 'f.lst [1] = value' अभिव्यक्ति नहीं है, लेकिन' f.lst .__ setitem __ (1, मान) 'है । – chepner

0

यह कंटेनर ऑब्जेक्ट्स की सामग्री के लिए काम करेगा। आप अपने चर (जो आप सी सूचक-टू-सूचक मामले में वैसे भी आवश्यकता होगी) को अविवेक से एक स्तर जोड़ने से परहेज नहीं करते हैं, तो आप कर सकते थे:

class Container(object): 

    def __init__(self, val): 
     self.val = val 

class Foo(object): 

    def __init__(self, target): 
     self.standalone = Container(3) 
     self.lst = [Container(4), Container(5), Container(6)] 

और तुम सच में की जरूरत नहीं होगी बिल्कुल पुन: असाइनर ऑब्जेक्ट।

Class Reassigner(object): 

    def __init__(self, target): 
     self.target = target 
    def reassign(self, value): 
     self.target.val = value 
1

यदि आपको असाइनमेंट को स्थगित करने की आवश्यकता है; आप functools.partial (या बस lambda) इस्तेमाल कर सकते हैं:

from functools import partial 

set_standalone = partial(setattr, f, "standalone") 
set_item = partial(f.lst.__setitem__, 1) 
set_standalone(7) 
set_item(9) 

हैं reassign केवल आपरेशन है; आपको एक नई कक्षा की आवश्यकता नहीं है। कार्य पाइथन में प्रथम श्रेणी के नागरिक हैं: आप उन्हें एक चर, स्टोर में स्टोर, तर्क के रूप में पास कर सकते हैं, आदि

+0

'operator.setitem' विशेषता केस में आइटम केस सममित बनाता है, और बेहतर दिखता है। – delnan

+0

@ डेलनान: मैंने इसके बारे में सोचा लेकिन मैं यह दिखाना चाहता था कि 'आंशिक' विधियों पर भी काम करता है (न केवल कार्यों) और पाइथन में भी विशेष तरीके हैं। अन्यथा 'operator.setitem' बेहतर हो सकता है क्योंकि यह '__setitem__' लुकअप को पोस्ट करता है (अपवाद कॉलर साइट पर हैं)। – jfs

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