पायथन में ए - = बी और ए = बी के बीच अंतर


90

मैंने हाल ही में मैट्रिक्स की हर एन पंक्तियों के औसत के लिए इस समाधान को लागू किया है । हालांकि समाधान सामान्य रूप से काम करता है जब मुझे 7x1 सरणी पर लागू किया गया था। मैंने देखा है कि समस्या -=ऑपरेटर का उपयोग करते समय है । एक छोटा सा उदाहरण बनाने के लिए:

import numpy as np

a = np.array([1,2,3])
b = np.copy(a)

a[1:] -= a[:-1]
b[1:] = b[1:] - b[:-1]

print a
print b

कौन से आउटपुट:

[1 1 2]
[1 1 1]

तो, एक सरणी के मामले में की a -= bतुलना में एक अलग परिणाम पैदा करता है a = a - b। मैंने अब तक सोचा था कि ये दोनों तरीके बिल्कुल एक जैसे हैं। अंतर क्या है?

कैसे एक मैट्रिक्स में हर एन पंक्तियों को समेटने के लिए मैं जिस विधि का उल्लेख कर रहा हूं वह काम कर रहा है जैसे 7x4 मैट्रिक्स के लिए लेकिन 7x1 सरणी के लिए नहीं?

जवाबों:


80

नोट: NumPy सरणी पर यथा-स्थान के संचालन का उपयोग कर उस संस्करण 1.13.0 आगे में नहीं रह गया है एक समस्या में हिस्सेदारी स्मृति (विवरण देखने के लिए यहाँ )। दो ऑपरेशन एक ही परिणाम का उत्पादन करेंगे। यह उत्तर केवल NumPy के पुराने संस्करणों पर लागू होता है।


जब वे अभिकलन में उपयोग किए जा रहे हैं तो सरणियों को म्यूट करना अप्रत्याशित परिणाम ला सकता है!

उदाहरण में प्रश्न में, -=के दूसरे तत्व के साथ घटाव को संशोधित करता है aऔर फिर तीसरे तत्व पर ऑपरेशन में उस संशोधित दूसरे तत्व का तुरंत उपयोग करता है a

यहाँ a[1:] -= a[:-1]कदम से कदम के साथ होता है :

  • aडेटा के साथ सरणी है [1, 2, 3]

  • इस डेटा पर हमारे दो विचार हैं: a[1:]है [2, 3], और a[:-1]है [1, 2]

  • जगह-जगह घटाव -=शुरू होता है। का पहला तत्व a[:-1], 1, के पहले तत्व से घटाया जाता है a[1:]। यह होने के लिए संशोधित किया aगया है [1, 1, 3]। अब हमारे पास a[1:]डेटा का एक दृश्य है [1, 3], और डेटा a[:-1]का एक दृश्य है [1, 1](सरणी aका दूसरा तत्व बदल दिया गया है)।

  • a[:-1]अब है [1, 1]और NumPy को अब अपने दूसरे तत्व को घटाना होगा जो कि दूसरे तत्व से 1 (2 नहीं है!) है a[1:]। यह a[1:]मूल्यों का एक दृश्य बनाता है [1, 2]

  • aअब मूल्यों के साथ एक सरणी है [1, 1, 2]

b[1:] = b[1:] - b[:-1]यह समस्या नहीं है क्योंकि पहले b[1:] - b[:-1]एक नया सरणी बनाता है और फिर इस सरणी में मान निर्दिष्ट करता है b[1:]। यह bघटाव के दौरान खुद को संशोधित नहीं करता है , इसलिए विचार b[1:]और b[:-1]परिवर्तन नहीं करते हैं।


सामान्य सलाह यह है कि यदि वे ओवरलैप करते हैं तो एक दृश्य को दूसरे के साथ बदलने से बचें। इस ऑपरेटरों शामिल -=, *=आदि और का उपयोग कर out(जैसे सार्वभौमिक कार्यों में पैरामीटर np.subtractऔर np.multiply) सरणियों से एक के लिए वापस लिखने के लिए।


4
मैं वर्तमान में स्वीकृत एक के लिए इस उत्तर को अधिक पसंद करता हूं। यह जगह में परिवर्तनशील वस्तुओं को संशोधित करने के प्रभाव को दिखाने के लिए बहुत स्पष्ट भाषा का उपयोग करता है। इससे भी महत्वपूर्ण बात, अंतिम पैराग्राफ सीधे ओवरलैपिंग विचारों के लिए इन-प्लेस संशोधन के महत्व पर जोर देता है, जो इस प्रश्न को घर ले जाने के लिए सबक होना चाहिए।
२३

43

आंतरिक रूप से, अंतर यह है कि यह:

a[1:] -= a[:-1]

इसके बराबर है:

a[1:] = a[1:].__isub__(a[:-1])
a.__setitem__(slice(1, None, None), a.__getitem__(slice(1, None, None)).__isub__(a.__getitem__(slice(1, None, None)))

जबकि यह:

b[1:] = b[1:] - b[:-1]

यह करने के लिए नक्शे:

b[1:] = b[1:].__sub__(b[:-1])
b.__setitem__(slice(1, None, None), b.__getitem__(slice(1, None, None)).__sub__(b.__getitem__(slice(1, None, None)))

कुछ मामलों में, __sub__()और __isub__()इसी तरह से काम करते हैं। लेकिन उत्परिवर्तित वस्तुओं को उत्परिवर्तित करना चाहिए और उपयोग __isub__()करते समय खुद को वापस करना चाहिए, जबकि उन्हें एक नई वस्तु के साथ वापस लौटना चाहिए __sub__()

खस्ता वस्तुओं पर टुकड़ा संचालन लागू करने से उन पर विचार पैदा होता है, इसलिए उनका उपयोग करके सीधे "मूल" ऑब्जेक्ट की मेमोरी तक पहुंच होती है।


11

डॉक्स कहते हैं:

पायथन में संवर्धित कार्य के पीछे का विचार यह है कि यह बाइनरी ऑपरेशन के परिणाम को अपने बाएं हाथ के ऑपरेंड में संग्रहीत करने के सामान्य अभ्यास को लिखने का एक आसान तरीका नहीं है, लेकिन सवाल में बाएं हाथ के ऑपरेंड के लिए एक तरीका भी है यह जान लें कि इसे स्वयं की संशोधित प्रति बनाने के बजाय `स्वयं संचालित’ करना चाहिए।

एक अंगूठे के नियम के रूप में, संवर्धित घटाव ( x-=y) IN -place ऑपरेशन के x.__isub__(y)लिए है , यदि संभव हो, जब सामान्य विकल्प ( ) हो । पूर्णांक जैसी गैर-परिवर्तनशील वस्तुओं पर यह समतुल्य है। लेकिन सरणियों या सूचियों जैसे परस्पर योग्य लोगों के लिए, आपके उदाहरण में, वे बहुत अलग चीजें हो सकती हैं।x = x-yx=x.__sub__(y)

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.