2010-12-29 37 views
7

कहो की सूची मैं दो सूचियों है:अजगर बुनियादी डेटा संदर्भ, एक ही संदर्भ

>>> l1=[1,2,3,4] 
>>> l2=[11,12,13,14] 

मैं एक टपल, या शब्दकोश में उन सूचियों रख सकते हैं, और ऐसा लगता है कि वे सभी संदर्भों को मूल सूची में वापस आ रहे हैं :

>>> t=(l1,l2) 
>>> d={'l1':l1, 'l2':l2} 
>>> id(l1)==id(d['l1'])==id(t[0]) 
True 
>>> l1 is d['l1'] is t[0] 
True 

क्योंकि वे संदर्भ हैं, मैं l1 बदल सकते हैं और टपल और शब्दकोश तदनुसार परिवर्तन में संदर्भित किया जाता डेटा कर सकते हैं:

>>> l1.append(5) 
>>> l1 
[1, 2, 3, 4, 5] 
>>> t 
([1, 2, 3, 4, 5], [11, 12, 13, 14]) 
>>> d 
{'l2': [11, 12, 13, 14], 'l1': [1, 2, 3, 4, 5]} 

सहित अगर मैं टपल t में शब्दकोश d या परिवर्तनशील संदर्भ में संदर्भ संलग्न:

>>> d['l1'].append(6) 
>>> t[0].append(7) 
>>> d 
{'l2': [11, 12, 13, 14], 'l1': [1, 2, 3, 4, 5, 6, 7]} 
>>> l1 
[1, 2, 3, 4, 5, 6, 7] 

अब मैं एक नई सूची में l1 सेट करते हैं, मूल सूची के लिए संदर्भ गिनती कम हो जाती है:

>>> sys.getrefcount(l1) 
4 
>>> sys.getrefcount(t[0]) 
4 
>>> l1=['new','list'] 
>>> l1 is d['l1'] is t[0] 
False 
>>> sys.getrefcount(l1) 
2 
>>> sys.getrefcount(t[0]) 
3 

और l1 को जोड़ना या बदलना d['l1'] या t[0] नहीं बदलता है क्योंकि यह अब एक नया संदर्भ है। पाइथन दस्तावेजों में अप्रत्यक्ष संदर्भों की धारणा covered fairly well है लेकिन पूरी तरह से नहीं।

मेरे सवालों का:

  1. एक परिवर्तनशील वस्तु हमेशा एक संदर्भ है? क्या आप हमेशा मानते हैं कि इसे संशोधित करने से मूल को संशोधित किया जाता है (जब तक आप विशेष रूप से l2=l1[:] प्रकार की मूर्खता के साथ प्रतिलिपि बनाते हैं)?

  2. क्या मैं पाइथन में सभी संदर्भों की एक सूची एकत्र कर सकता हूं? यानी, कुछ फ़ंक्शन f(l1) जो ['l1', 'd', 't'] लौटाता है यदि वे सभी एक ही सूची का जिक्र कर रहे हैं?

  3. यह मेरी धारणा है कि इससे कोई फर्क नहीं पड़ता कि डेटा तब तक वैध रहेगा जब तक इसका कुछ संदर्भ न हो।

अर्थात्:

l=[1,2,3]   # create an object of three integers and create a ref to it 
l2=l    # create a reference to the same object 
l=[4,5,6]   # create a new object of 3 ints; the original now referenced 
        # by l2 is unchanged and unmoved 
+0

3 के लिए प्रासंगिक: http://docs.python.org/library/weakref.html –

उत्तर

6

1) एक संदर्भ के माध्यम से एक परिवर्तनशील वस्तु को संशोधित हमेशा को संशोधित करेगा "मूल"। ईमानदारी से, यह संदर्भों की गलतफहमी को धोखा दे रहा है। नया संदर्भ उतना ही "मूल" है जितना कि कोई अन्य संदर्भ है। जब तक दोनों नाम एक ही वस्तु को इंगित करते हैं, तो किसी अन्य नाम के माध्यम से ऑब्जेक्ट को संशोधित करने पर दूसरे नाम के माध्यम से उपयोग किया जाएगा।

2) बिल्कुल वही पसंद नहीं है जो आप चाहते हैं। gc.get_referrers ऑब्जेक्ट के संदर्भ सभी रिटर्न।

>>> l = [1, 2] 
>>> d = {0: l} 
>>> t = (l,) 
>>> import gc 
>>> import pprint 
>>> pprint.pprint(gc.get_referrers(l)) 
[{'__builtins__': <module '__builtin__' (built-in)>, 
    '__doc__': None, 
    '__name__': '__main__', 
    '__package__': None, 
    'd': {0: [1, 2]}, 
    'gc': <module 'gc' (built-in)>, 
    'l': [1, 2], 
    'pprint': <module 'pprint' from '/usr/lib/python2.6/pprint.pyc'>, 
    't': ([1, 2],)}, # This is globals() 

{0: [1, 2]}, # This is d 
([1, 2],)] # this is t 

ध्यान दें कि वास्तविक l द्वारा संदर्भित वस्तु लौटे सूची में शामिल नहीं है, क्योंकि यह अपने आप के लिए एक संदर्भ शामिल नहीं है। globals() लौटा दिया गया है क्योंकि में मूल सूची का संदर्भ है।

3) यदि वैध है, तो आपका मतलब है "कचरा नहीं होगा" तो यह एक बेहद असंभव बग को छोड़कर सही है। यह एक बहुत ही खेदजनक कचरा कलेक्टर होगा जो आपके डेटा को "चुरा लिया"।

0

1- क्या एक उत्परिवर्तनीय वस्तु हमेशा संदर्भ है? क्या आप हमेशा यह मान सकते हैं कि इसे संशोधित करने से मूल संशोधित हो जाता है (जब तक आप विशेष रूप से l2 = l1 [:] idiom के साथ प्रतिलिपि बनाते हैं)?

हां। असल में गैर-परिवर्तनीय वस्तुएं हमेशा एक संदर्भ भी होती हैं। आप इसे समझने के लिए बस उन्हें बदल नहीं सकते हैं।

2 - मैं अजगर में सभी ही संदर्भों की एक सूची को इकट्ठा कर सकते हैं? यानी, कुछ फ़ंक्शन f (l1) जो ['l1', 'd', 't'] लौटाता है, यदि वे सभी एक ही सूची का जिक्र करते हैं?

यह अजीब है, लेकिन यह किया जा सकता है।

आप is ऑपरेटर के साथ "samenes" के लिए ऑब्जेक्ट्स की तुलना कर सकते हैं। आप देख सकते हैं जो इन संदर्भों के is ऑपरेटर के साथ आपके वस्तु ओ बात - l1 is t[0]

में पसंद है और आप सभी के लिए भेजा करने के लिए समारोह कचरा कलेक्टर मॉड्यूल (जीसी) में gc.get_referrers के साथ वस्तुओं मिल सकती है। तो, हाँ, यह किया जा सकता है। मुझे नहीं लगता कि यह एक अच्छा विचार होगा। यह अधिक संभावना is ऑपरेटर प्रस्ताव तुम क्या तुम अकेले जरूरत

3- यह मेरी धारणा है कि कोई फर्क नहीं पड़ता क्या, डेटा मान्य रहेगा करने के लिए एक तरह से तो लंबे वहाँ कुछ संदर्भ के रूप में है इसके लिए

हां।

0

क्या एक उत्परिवर्तनीय वस्तु हमेशा एक संदर्भ है? क्या आप हमेशा यह मान सकते हैं कि इसे संशोधित करने से मूल को संशोधित किया जाता है (जब तक आप विशेष रूप से l2 = l1 [:] idiom के साथ प्रतिलिपि बनाते हैं)?

अजगर संदर्भ अर्थ विज्ञान है: चर सी में के रूप में नहीं दुकान मान कर ++, लेकिन इसके बजाय लेबल उन्हें। "मूल" की अवधारणा त्रुटिपूर्ण है: यदि दो चर समान मूल्य लेबल करते हैं, तो यह पूरी तरह से अप्रासंगिक है जो एक "पहले आया" है। इससे कोई फर्क नहीं पड़ता कि वस्तु उत्परिवर्तनीय है या नहीं (सिवाय इसके कि अपरिवर्तनीय वस्तुएं दृश्यों के पीछे क्या हो रहा है यह बताना इतना आसान नहीं होगा)। प्रतियों को अधिक सामान्य उद्देश्य से बनाने के लिए, copy मॉड्यूल आज़माएं।

क्या मैं पाइथन में सभी संदर्भों की एक सूची एकत्र कर सकता हूं? यानी, कुछ फ़ंक्शन f (l1) जो ['l1', 'd', 't'] लौटाता है, यदि वे सभी एक ही सूची का जिक्र कर रहे हैं?

आसानी से नहीं। विवरण के लिए अरोर्नस्टरिंग का जवाब देखें।तुम भी k for k, v in locals().items() if v is the_object की तरह कुछ की कोशिश कर सकते हैं, लेकिन आप भी globals() खोज करने के लिए होगा, आप कुछ सामान को खो देंगे और यह कारण नाम 'k' और 'वी' के साथ recursing को समस्याओं के कुछ प्रकार के कारण हो सकता है (मैं नहीं है परीक्षण किया)।

यह मेरी धारणा है कि इससे कोई फर्क नहीं पड़ता कि डेटा तब तक वैध रहेगा जब तक इसका कुछ संदर्भ न हो।

बिल्कुल।

0
  1. "... ऑब्जेक्ट एक संदर्भ है ..." बकवास है। संदर्भ वस्तुएं नहीं हैं। चर, सदस्य फ़ील्ड, सूचियों और सेटों, आदि में स्लॉट संदर्भ धारण करते हैं, और ये संदर्भ वस्तुओं को इंगित करते हैं। किसी ऑब्जेक्ट के संदर्भ में कोई भी संख्या हो सकती है (गैर-रीफ्रूटिंग कार्यान्वयन में, यहां तक ​​कि कोई भी अस्थायी रूप से, यानी जीसी में आने तक)। प्रत्येक व्यक्ति जो एक वस्तु के लिए एक संदर्भ यह तरीकों है आह्वान कर सकते हैं है, का उपयोग यह सदस्य है, आदि - इस सभी वस्तुओं के लिए सच है। बेशक केवल परिवर्तनीय वस्तुओं को इस तरह से बदला जा सकता है, इसलिए आप आमतौर पर अपरिवर्तनीय लोगों की परवाह नहीं करते हैं।
  2. हाँ, के रूप में दूसरों से पता चला है। लेकिन यह तब तक जरूरी नहीं होना चाहिए जब तक आप या तो जीसी डिबग नहीं कर रहे हों या अपने कोड में गंभीर मेमोरी रिसाव को ट्रैक न करें - आपको ऐसा क्यों लगता है कि आपको इसकी आवश्यकता है?
  3. पायथन स्वचालित स्मृति प्रबंधन हाँ है, तो। जब तक किसी ऑब्जेक्ट का संदर्भ होता है, तब तक इसे हटाया नहीं जाएगा (हालांकि, यह चक्कर आने के बाद थोड़ी देर के लिए ज़िंदा रह सकता है, चक्रीय संदर्भों के कारण और तथ्य यह है कि जीसी केवल थोड़ी देर में चलती है)।
3

अजगर में हर चर एक संदर्भ है।

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

list.append(x)method specificallyl[len(l):]=[list]

तो के बराबर है:

>>> l1=range(3) 
>>> l2=range(20,23) 
>>> l3=range(30,33) 
>>> l1[len(l1):]=[l2] # equivalent to 'append' for subscriptable sequences 
>>> l1[len(l1):]=l3  # same as 'extend' 
>>> l1 
[0, 1, 2, [20, 21, 22], 30, 31, 32] 
>>> len(l1) 
7 
>>> l1.index(30) 
4 
>>> l1.index(20) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
ValueError: list.index(x): x not in list 
>>> 20 in l1 
False 
>>> 30 in l1 
True 

l1[len(l1):]=[l2] में l2 आसपास सूची निर्माता डाल, या l.append(l2) बुला करके, आप एक संदर्भ है कि l2 के लिए बाध्य है बनाएँ। यदि आप एल 2 बदलते हैं, तो संदर्भ भी बदलाव दिखाएंगे। सूची में उस की लंबाई एक तत्व है - अनुक्रमित अनुक्रम का संदर्भ।

l1[len(l1):]=l3 में कोई कन्स्ट्रक्टर शॉर्टकट नहीं है, तो आप अनुक्रम के प्रत्येक तत्व की प्रतिलिपि बनाते हैं।

आप इस तरह के l.index(something) ही अन्य सामान्य सूची के तरीकों, उपयोग करें, या in आप डेटा संदर्भ के अंदर तत्वों नहीं मिल जाएगा। l.sort() ठीक से सॉर्ट नहीं करेगा। वे ऑब्जेक्ट पर "उथले" संचालन हैं, और l1[len(l1):]=[l2] का उपयोग कर अब आप एक रिकर्सिव डेटा संरचना बना रहे हैं।

यदि आप l1[len(l1):]=l3 का उपयोग करते हैं, तो आप l3 में तत्वों की एक वास्तविक (उथली) प्रति बना रहे हैं।

ये काफी मौलिक पायथन मुहावरे हैं, और अधिकांश समय वे सही काम करते हैं। हालांकि, आप इस तरह के रूप आश्चर्यजनक परिणाम प्राप्त कर सकते हैं:

>>> m=[[None]*2]*3 
>>> m 
[[None, None], [None, None], [None, None]] 
>>> m[0][1]=33 
>>> m 
[[None, 33], [None, 33], [None, 33]] # probably not what was intended... 
>>> m[0] is m[1] is m[2]    # same object, that's why they all changed 
True 

कुछ अजगर newbies के रूप में उम्मीद m=[[None]*2]*3 पहले sequence replication काम करता है की तरह कुछ कर रही द्वारा एक बहु आयाम बनाने का प्रयास करें; यह None की 2 प्रतियां बनाता है। यह दूसरा मुद्दा है जो मुद्दा है: यह पहली सूची के संदर्भ की तीन प्रतियां बनाता है। इसलिए m[0][1]=33 दर्ज करने से सूची में सूची को संशोधित किया गया है और फिर सभी बाध्य संदर्भ उस परिवर्तन को दिखाने के लिए बदलते हैं।

से तुलना करें:

>>> m=[[None]*2,[None]*2,[None]*2] 
>>> m 
[[None, None], [None, None], [None, None]] 
>>> m[0][1]=33 
>>> m 
[[None, 33], [None, None], [None, None]] 

तुम भी nested list comprehensions उपयोग कर सकते हैं ताकि जैसे ही करने के लिए:

>>> m=[[ None for i in range(2)] for j in range(3)] 
>>> m 
[[None, None], [None, None], [None, None]] 
>>> m[0][1]=44 
>>> m 
[[None, 44], [None, None], [None, None]] 
>>> m[0] is m[1] is m[2]      # three different lists.... 
False 

सूचियों और संदर्भ के लिए, फ्रेड्रिक Lundh एक अच्छा परिचय के लिए this text है।

अपने विशिष्ट प्रश्नों के रूप में:

1) पायथन में, सब कुछ एक लेबल या किसी वस्तु के लिए एक संदर्भ है। कोई 'मूल' (एक सी ++ अवधारणा नहीं है) और 'संदर्भ', सूचक, या वास्तविक डेटा (सी/पर्ल अवधारणा)

2) के बीच कोई भेद नहीं है। फ्रेड्रिक लंदन के संदर्भ में to a question similar to this संदर्भ में एक महान सादृश्य है:

उसी तरह आपको लगता है कि बिल्ली आप अपने बरामदे पर पाया के नाम के रूप में: बिल्ली (वस्तु) ही आपको बता सकता है नहीं कि इसके नाम से, और यह वास्तव में परवाह नहीं करता - तो यह जानने का एकमात्र तरीका यह है कि इसे आपके पड़ोसियों (नामस्थान) से पूछना है कि क्या यह बिल्ली (ऑब्जेक्ट) है ...

.... और अगर आप देखेंगे तो यह आश्चर्यचकित नहीं होगा कि यह कई नामों से ज्ञात है, या कोई नाम नहीं है!

आप इस सूची को कुछ प्रयास के साथ पा सकते हैं, लेकिन क्यों? बस इसे कॉल करें जिसे आप इसे कॉल करने जा रहे हैं - एक मिली बिल्ली की तरह।

3) सच है।

0
1a. Is a mutable object always a reference? 

परिवर्तनीय और गैर-परिवर्तनीय वस्तुओं के बीच कोई अंतर नहीं है। परिवर्तनीय नामों को संदर्भ के रूप में देखना सी-पृष्ठभूमि वाले लोगों के लिए सहायक होता है (लेकिन इसका तात्पर्य है कि उन्हें संदर्भित किया जा सकता है, जो वे नहीं कर सकते हैं)।

1b. Can you always assume that modifying it modifies the original 

कृपया, यह "मूल" नहीं है। यह वही वस्तु है। बी = एक मतलब बी और अब एक ही वस्तु है।

1c. (Unless you specifically make a copy with l2=l1[:] kind of idiom)? 

ठीक है, क्योंकि तब यह वही वस्तु नहीं है। (हालांकि सूची एन प्रविष्टियां मूल सूची के समान वस्तुएं होंगी)।

2. Can I assemble a list of all the same references in Python? 

हाँ, शायद, लेकिन आप कभी नहीं कभी कभी, यह आवश्यकता होगी ताकि ऊर्जा की बर्बादी होगी। :)

3. It is my assumption that no matter what, the data will remain valid so long as there is some reference to it. 

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

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