2016-03-17 6 views
6

के अंदर एक NumPy सरणी स्लाइसिंग मुझे (के लिए) loops के भीतर NumPy टुकड़ा व्याख्या करने के लिए एक अच्छा स्पष्टीकरण (संदर्भ) की आवश्यकता है। मेरे पास तीन मामले हैं।लूप

def example1(array): 
    for row in array: 
     row = row + 1 
    return array 

def example2(array): 
    for row in array: 
     row += 1 
    return array 

def example3(array): 
    for row in array: 
     row[:] = row + 1 
    return array 

एक साधारण मामला:

ex1 = np.arange(9).reshape(3, 3) 
ex2 = ex1.copy() 
ex3 = ex1.copy() 

रिटर्न:

>>> example1(ex1) 
array([[0, 1, 2], 
     [3, 4, 5], 
     [6, 7, 8]]) 

>>> example2(ex2) 
array([[1, 2, 3], 
     [4, 5, 6], 
     [7, 8, 9]]) 

>>> example3(ex3) 
array([[1, 2, 3], 
     [4, 5, 6], 
     [7, 8, 9]]) 

यह देखा जा सकता है कि पहला परिणाम दूसरे और तीसरे से अलग है।

+2

संबंधित प्रश्न, उम्मीद है कि यह मदद करता है http://stackoverflow.com/questions/15376509/when-is-i-x-different-from-i-i-x-in-python/15376520#15376520 – Thiru

उत्तर

4

पहले उदाहरण:

आप एक पंक्ति निकालने और इसे करने के लिए 1 जोड़ें। फिर आप को रीफिफाइन सूचकrow लेकिन array में क्या नहीं है! तो यह मूल सरणी को प्रभावित नहीं करेगा।

दूसरा उदाहरण:

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

आप एक डबल पाश कर रहे थे, तो इसे अब और काम नहीं होगा:

def example4(array): 
    for row in array: 
     for column in row: 
      column += 1 
    return array 

example4(np.arange(9).reshape(3,3)) 
array([[0, 1, 2], 
     [3, 4, 5], 
     [6, 7, 8]]) 

इस क्योंकि आप कॉल नहीं करते काम नहीं करता है np.ndarray के __iadd__ (डेटा सरणी बिंदुओं को संशोधित कर के लिए) लेकिन पायथन int के __iadd__। तो यह उदाहरण केवल काम करता है क्योंकि आपकी पंक्तियां numpy arrays हैं।

तीसरा उदाहरण:

row[:] = row + 1 यह फिर से इस जगह में काम करता है row[0] = row[0]+1, row[1] = row[1]+1, ... की तरह कुछ के रूप में व्याख्या तो यह मूल सरणी प्रभावित करता है।

बॉटम लाइन

आप list या np.ndarray आप क्या बदल सावधान रहना चाहिए, जैसे परिवर्तनशील वस्तुओं पर काम कर रहे हैं। इस तरह की एक वस्तु केवल अंक जहां वास्तविक डेटा स्मृति में संग्रहीत किया जाता है - इसलिए सूचक (example1) को सहेजने वाले डेटा को प्रभावित नहीं करता है। सहेजे गए डेटा को बदलने के लिए आपको पॉइंटर का पालन करना होगा (या तो सीधे [:] (example3) या परोक्ष रूप से array.__iadd__ (example2) के साथ।

3

पहले कोड में, आप नई गणना वाली पंक्ति के साथ कुछ भी नहीं करते हैं; आप नाम row पर पुनर्निर्मित करते हैं, और अब सरणी से कोई कनेक्शन नहीं है।

दूसरे और तीसरे में, आप rebind नहीं करते हैं, लेकिन पुराने चर को मान असाइन करते हैं। += के साथ कुछ आंतरिक फ़ंक्शन कहा जाता है, जो उस ऑब्जेक्ट के प्रकार के आधार पर भिन्न होता है जिस पर आप इसे कार्य करते हैं। नीचे दिए गए लिंक देखें।

यदि आप दाईं तरफ row + 1 लिखते हैं, तो एक नई सरणी की गणना की जाती है। पहले मामले में, आप इसे नामrow (और मूल ऑब्जेक्ट को भूल जाएं जिसे पहले row कहा जाता था) को पाइथन बताएं।और तीसरे में, नई सरणी पुराने row के टुकड़े पर लिखी गई है।

आगे पढ़ने के लिए उपरोक्त @ तीरू द्वारा प्रश्न के टिप्पणी का पालन करें। या assignment and rebinding in general...