2013-03-28 5 views
8

मैं धीरे-धीरे view एस और copy एस के बीच अंतर, साथ ही उत्परिवर्तनीय बनाम अपरिवर्तनीय प्रकारों के बीच अंतर को समझने की कोशिश कर रहा हूं।उन्नत इंडेक्सिंग कॉपी सरणी डेटा के साथ असाइनमेंट करता है?

यदि मैं 'advanced indexing' के साथ किसी सरणी का हिस्सा एक्सेस करता हूं तो इसे एक प्रतिलिपि वापस लेनी होगी। यह सच हो रहा है:

In [1]: import numpy as np 
In [2]: a = np.zeros((3,3)) 
In [3]: b = np.array(np.identity(3), dtype=bool) 

In [4]: c = a[b] 

In [5]: c[:] = 9 

In [6]: a 
Out[6]: 
array([[ 0., 0., 0.], 
     [ 0., 0., 0.], 
     [ 0., 0., 0.]]) 

c के बाद से सिर्फ एक प्रति है, यह डेटा साझा नहीं करता और इसे बदलने a उत्परिवर्तित नहीं करता है। बहरहाल, यह क्या मुझे confuses है:

In [7]: a[b] = 1 

In [8]: a 
Out[8]: 
array([[ 1., 0., 0.], 
     [ 0., 1., 0.], 
     [ 0., 0., 1.]]) 

तो, ऐसा लगता है, भले ही मैं उन्नत अनुक्रमण का उपयोग करें, काम अभी भी एक दृश्य के रूप में छोड़ दिया पर बात व्यवहार करता है। लाइन 2 में स्पष्ट रूप से a लाइन 2 में a के समान ऑब्जेक्ट/डेटा है, क्योंकि c पर इसका कोई प्रभाव नहीं पड़ता है।

तो मेरा प्रश्न: a लाइन 8 में वही वस्तु/डेटा पहले (पाठ्यक्रम के विकर्ण की गणना नहीं) है या यह एक प्रति है? दूसरे शब्दों में, a का डेटा नए a पर कॉपी किया गया था, या उसका डेटा जगह में बदल गया था?

उदाहरण के लिए, यह पसंद है:

x = [1,2,3] 
x += [4] 

या की तरह:

y = (1,2,3) 
y += (4,) 

मैं क्योंकि या तो मामले में यह जांच करने के लिए कैसे पता नहीं है, a.flags.owndataTrue है। अगर मैं इस बारे में किसी भ्रमित तरीके से सोच रहा हूं तो कृपया एक अलग प्रश्न का विस्तार करने या जवाब देने में संकोच न करें।

उत्तर

6

जब आप c = a[b] करते हैं, a.__get_item__b अपने ही तर्क के रूप में के साथ कहा जाता है, और जो कुछ भी वापस आ जाता है c को सौंपा गया है।

जब आप a[b] = c करते हैं, a.__setitem__ तर्कों के रूप b और c साथ कहा जाता है और जो कुछ भी वापस आ जाता है चुपचाप त्याग दिया जाता है।

तो a[b] वाक्यविन्यास होने के बावजूद, दोनों अभिव्यक्ति अलग-अलग चीजें कर रही हैं।आप ndarray उपclass कर सकते हैं, इन दो कार्यों को अधिभारित करें, और उन्हें अलग-अलग व्यवहार करें। जैसा कि डिफ़ॉल्ट रूप से numpy में है, पूर्व एक प्रतिलिपि देता है (यदि b एक सरणी है) लेकिन बाद में a जगह में संशोधित करता है।

+0

मुझे लगता है कि यह स्पष्ट रूप से numpy दस्तावेज में स्पष्ट रूप से इंगित करने के लायक होगा कि तथ्य यह है कि जब भी lvalue के रूप में उपयोग किया जाता है तो उन्नत अनुक्रमण भी मूल सरणी को संशोधित करेगा। – vehsakul

3

हां, यह वही वस्तु है। सिर्फ इतना है कि अभिव्यक्ति के मूल्य को पढ़ने के रूप में ही नहीं

>>> a 
array([[ 0., 0., 0.], 
     [ 0., 0., 0.], 
     [ 0., 0., 0.]]) 
>>> a2 = a 
>>> a[b] = 1 
>>> a2 is a 
True 
>>> a2 
array([[ 1., 0., 0.], 
     [ 0., 1., 0.], 
     [ 0., 0., 1.]]) 

अजगर में कुछ अभिव्यक्ति के लिए नियत है: यहाँ आप कैसे की जाँच है। जब आप c = a[b] करते हैं, तो बराबर चिह्न के दाईं ओर a[b] के साथ, यह एक नई वस्तु देता है। जब आप a[b] = 1 करते हैं, तो बराबर चिह्न के बाईं ओर a[b] के साथ, यह मूल वस्तु को संशोधित करता है।

वास्तव में, a[b] = 1 की तरह एक अभिव्यक्ति नहीं कर सकते हैं परिवर्तन क्या नाम a के लिए बाध्य है। कोड जो obj[index] = value को संभालता है केवल ऑब्जेक्ट obj को जानता है, उस ऑब्जेक्ट को संदर्भित करने के लिए किस नाम का उपयोग नहीं किया गया था, इसलिए यह उस नाम को नहीं बदल सकता है जो उस नाम से संदर्भित है।

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