2017-12-29 159 views
12

मैं कोड (एक तरह से) निम्नलिखित में आए:यह सूची स्लाइसिंग असाइनमेंट के साथ कैसे विस्तारित की जाती है?

my_list = [1, [2, 3, 4], 5] 
my_list[1:2] = my_list[1] 

इन दो पंक्तियों चलाने के बाद, चर my_list[1, 2, 3, 4, 5] हो जाएगा। नेस्टेड सूचियों का विस्तार करने के लिए बहुत उपयोगी है।

लेकिन वास्तव में ऐसा क्यों करता है जो यह करता है?

मैं मान लिया है कि बयान my_list[1:2] = my_list[1] निम्न में से एक करना होगा:

  • बस दूसरी सूची में स्थिति (जहां यह पहले से ही है)
  • भी किसी तरह का देना "में [2, 3, 4] डाल "मान को अनपैक करने के लिए कई मान, केवल तीन लंबाई (अर्थात् my_list[1:2]) के कंटेनर में तीन मान (अर्थात् 2,3,4) डालने की कोशिश करने से। (एक ऐसी ही गलती से एक सूची परिणामों के बजाय एक Numpy सरणी के साथ ऊपर दोहरा।)

अन्य प्रश्न (जैसे How assignment works with python list slice) हिस्से के आकार के बीच अंतर आ ज्यादा ध्यान नहीं करने के लिए प्रतिस्थापित किया जा के लिए करते हैं, और जिन वस्तुओं को आप बदल रहे हैं उनका आकार। (का कारण बताते हुए जिस तरह से यह करता है काम करता है अकेले चलो।)

+0

'my_list = [1,2,3]; my_list [1: 2] = [9,8,7] '=>' [1, 9, 8, 7,3] 'मैंने सोचा कि यह पाइथन का सामान्य व्यवहार है जबकि सूची – splash58

+0

के साथ स्लाइस को प्रतिस्थापित करना इस' my_list [1: 2] = [my_list [1]] ' – Artier

+0

मैंने स्पष्ट रूप से उल्लेख करने के लिए उत्तर में से एक उत्तर संपादित किया है कि आप असाइनमेंट के दोनों किनारों पर विभिन्न आकार की सूचियों का उपयोग कर सकते हैं। * "अकेले बताएं कि यह किस तरह से काम करता है।" * आप किस तरह के उत्तर की उम्मीद करते हैं? https://stackoverflow.com/a/10623352/2301450 और https://stackoverflow.com/a/35632876/2301450 दोनों सही हैं। – vaultah

उत्तर

5

Slice assignment सूची के निर्दिष्ट भाग को दाईं ओर दाईं ओर से बदलकर सूची के बीच डालने के बजाय एक सूची के बीच डालने जा रहे हैं, जो अलग-अलग हो सकता है टुकड़ा की तुलना में लंबाई। चेहरे के मूल्य पर सवाल उठाते हुए, ऐसा क्यों कारण है क्योंकि यह सुविधाजनक है।

आप वास्तव में स्लाइस को असाइन नहीं कर रहे हैं, यानी पायथन एक टुकड़ा ऑब्जेक्ट नहीं बनाता है जिसमें सूची से निर्दिष्ट मान होते हैं और फिर इन मानों को बदलते हैं। एक कारण जो काम नहीं करेगा यह है कि स्लाइसिंग एक नई सूची देता है, इसलिए यह ऑपरेशन मूल सूची नहीं बदलेगा।

यह भी देखें this question, जो कि स्लाइसिंग और टुकड़ा असाइनमेंट पर जोर देता है पूरी तरह अलग है।

+0

यह उत्तर कुछ अन्य लोगों के समान है, एक वाक्य को छोड़कर, जो मुझे लगता है कि यह बहुत महत्वपूर्ण है: "ऐसा इसलिए है क्योंकि यह सुविधाजनक है"। सूची स्लाइस असाइनमेंट विशेष रूप से इस व्यवहार के लिए बनाया गया था, जरूरी नहीं कि यह तार्किक है (मुझे लगता है कि यह तार्किक नहीं है) लेकिन क्योंकि यह सुविधाजनक है। धन्यवाद! – acdr

-1
my_list[1:2] = my_list[1], Its simply a inserting statement, it translate to 

हम सिर्फ my_list1from my_list [1] my_list2 के बीच कुछ तत्व करने की कोशिश कर रहे हैं। अब यह सूची के समान ही है .extend (list1), बस हम

+3

यह केवल कथन का क्या अर्थ है, यह वास्तव में हुड के नीचे कैसे काम करता है। – acdr

2

लघु उत्तर:

my_list[1:2] = my_list[1] इच्छाशक्ति की my_list

स्पष्टीकरण 1 सूचकांक में मौजूद सामग्री के साथ my_list के 2 सूचकांक को 1 सूची से सामग्री की जगह:

चलो दो टुकड़ा करने की क्रिया संचालन, बहुत समान है, लेकिन पूरी तरह से अलग देखना

  1. यह सूची और यह भंडार चर

    some_variable = some_list[2:5] 
    
  2. यह की कॉपी बन जाती सूची inplace की सामग्री को बदल देता है, जो सूची की लंबाई को भी बदलता है।

    some_list[2:5] = [1, 2, 3, 4] 
    

आप असाइनमेंट ऑपरेटर = का उपयोग करते हैं, यह एक __setitem__ समारोह का आह्वान। यहां हमारा ध्यान उपरोक्त मामला 2 है। के रूप में प्रति Python's Assignment Statement दस्तावेज़:

यदि लक्ष्य है एक टुकड़ा करने की क्रिया: संदर्भ में प्राथमिक अभिव्यक्ति का मूल्यांकन किया है। यह एक परिवर्तनीय क्रम वस्तु (जैसे एक सूची) पैदा करना चाहिए। असाइन किया गया ऑब्जेक्ट एक ही प्रकार का अनुक्रम वस्तु होना चाहिए। अगला, निचले और ऊपरी बाध्य अभिव्यक्तियों का मूल्यांकन किया जाता है, वे मौजूद हैं; डिफ़ॉल्ट शून्य और अनुक्रम की लंबाई हैं। सीमाओं को पूर्णांक का मूल्यांकन करना चाहिए। यदि या तो बाध्य ऋणात्मक है, तो अनुक्रम की लंबाई इसमें शामिल की गई है। परिणामी सीमाएं पर शून्य और अनुक्रम की लंबाई के बीच झूठ बोलती हैं, समावेशी। अंत में, अनुक्रम ऑब्जेक्ट को असाइन किए गए अनुक्रम के आइटम के साथ स्लाइस को प्रतिस्थापित करने के लिए कहा जाता है। स्लाइस की लंबाई असाइन अनुक्रम की लंबाई से भिन्न हो सकती है, इस प्रकार लक्ष्य अनुक्रम की अनुमति देता है, तो लक्ष्य अनुक्रम की लंबाई बदलना।

में हमारे मामले my_list[1:2] = my_list[1], अजगर भी कॉल करेंगे __setitem__ के रूप में:

my_list.__setitem__(slice(1,2,None), [2, 3, 4]) 

देखें slice दस्तावेज़ को पता है कि वह क्या करता।

इसलिए, जब आप my_list[1:2] = my_list[1] किया था, आप my_list के 2 सूचकांक को 1 सूची से सामग्री my_list अर्थात [2, 3, 4] के 1 सूचकांक में मौजूद सामग्री के साथ बदल दिया।


मैं अब लगता है कि हम जवाब कर सकते हैं क्यों अपनी मान्यताओं सही नहीं हैं:

  • डाल [2, 3, 4] सूची में दूसरे स्थान पर (जहां यह पहले से ही है) में

नहीं। क्योंकि __setitem__ सूचकांक पर लेकिन सूचकांक जो आप पारित slice पर नहीं बुलाया जाता है।

  • त्रुटि "अनपैक करने के लिए बहुत अधिक मान", केवल लंबाई 1 के एक कंटेनर में तीन मूल्यों (अर्थात् 2,3,4) डाल करने के लिए कोशिश कर रहा से किसी तरह का देना (अर्थात् my_list [1: 2])।

फिर नहीं। क्योंकि अपने कंटेनर बनाने अपने सूचकांकों की रेंज मूल्यों के नए सेट के साथ बदल दिया है।

1

आप क्या कर रहे हैं slice assignment है।

स्लाइस को असाइनमेंट भी संभव है, और यह भी सूची का आकार बदलने के लिए या पूरी तरह से यह स्पष्ट

my_list[1:2] = my_list[1]

यह my_list[1] की सामग्री के साथ my_list का टुकड़ा की जगह कर सकते हैं।

असाइनमेंट ऑपरेटर = के बाईं ओर my_list[1:2] निर्दिष्ट करके, आप पाइथन को बता रहे हैं कि आप स्लाइस असाइनमेंट का उपयोग करना चाहते हैं।

my_list[1:2] = my_list[1], my_list.__setitem__(slice(1, 2, None), my_list[1])

slice में (1, 2, कोई नहीं) के बराबर है 1 शुरू है, 2 रोक है, और None कदम है और वैकल्पिक है।

2

यहाँ Python Language Reference

से प्रासंगिक सा है लक्ष्य एक टुकड़ा करने की क्रिया है: संदर्भ में प्राथमिक अभिव्यक्ति का मूल्यांकन किया है। यह एक परिवर्तनीय क्रम वस्तु (जैसे एक सूची) पैदा करना चाहिए। असाइन किया गया ऑब्जेक्ट एक ही प्रकार का अनुक्रम वस्तु होना चाहिए। अगला, निचले और ऊपरी बाध्य अभिव्यक्तियों का मूल्यांकन किया जाता है, वे मौजूद हैं; डिफ़ॉल्ट शून्य और अनुक्रम की लंबाई हैं। सीमाओं को पूर्णांक का मूल्यांकन करना चाहिए। यदि या तो बाध्य ऋणात्मक है, तो अनुक्रम की लंबाई इसमें शामिल की गई है। परिणामी सीमाएं पर शून्य और अनुक्रम की लंबाई के बीच झूठ बोलती हैं, समावेशी। अंत में, अनुक्रम ऑब्जेक्ट को असाइन किए गए अनुक्रम के आइटम के साथ स्लाइस को प्रतिस्थापित करने के लिए कहा जाता है। स्लाइस की लंबाई असाइन अनुक्रम की लंबाई से भिन्न हो सकती है, इस प्रकार लक्ष्य अनुक्रम की अनुमति देता है, तो लक्ष्य अनुक्रम की लंबाई बदल रहा है।क्योंकि जब आप एक सूची स्लाइस आप एक उप सूची तो जगह है कि एक और सूची के साथ घोंसले का एक स्तर नहीं जोड़ना चाहिए पाने

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

0

जो आप कर रहे हैं वह स्लाइसिंग के माध्यम से एक तत्व डालना है। मैं भागों से सब कुछ समझाऊंगा। वांछित श्रेणी में लक्ष्य सूची को स्लाइस करने के बाद इसे एक सूची में शामिल करने से अधिक आपकी सूची में एक आइटम जोड़ने के रूप में व्याख्या की जा सकती है। अब प्रत्येक पंक्ति को विस्तार से समझाएं:

my_list[1:2] 

वह हिस्सा पायथन को कहने जैसा है; "मैं इंडेक्स 1 से मानों (स्लाइस) को 2 से पहले इंडेक्स में प्राप्त करना चाहता हूं (2 को छोड़कर, मैं बाद में एक और उदाहरण के साथ समझाऊंगा)"। उसके बाद आप उन मूल्यों को कोई मान निर्दिष्ट:

my_list[1:2] = my_list[1] #The same as my_list[1:2] = [2,3,4] 

अब आप जानते हैं कि क्या पहले भाग करता है, तो उसके आगे '=' ऑपरेटर के दाईं ओर आइटम जोड़ने के लिए, तो आप इसे व्याख्या की जा सकती जा रहा है इस तरह; "मैं इंडेक्स 1 से 2 से पहले सब कुछ (फिर से, इंडेक्स 2 को छोड़कर) से टुकड़ा करना चाहता हूं और फिर मेरी सूची [2,3,4]" जोड़ना चाहता हूं। अब यहां एक और उदाहरण आते हैं ताकि आप उम्मीद कर सकें कि मैं भी बेहतर हूं। http://effbot.org/zone/python-list.htm Understanding Python's slice notation How assignment works with python list slice

आशा:

[1,2,3,4,5] #List before line of code: myList[1:3] = [12,13,14] 
[1,|2,3|,4,5] #The moment where you slice the list with: myList[1:3]. Please notice that the characters used '|' are for representing the slice. 
[1] + [12,13,14] + [4,5] #After assigning what the slice should be changed for. It's like excracting from the whole list the values [2,3] and changing it for [12,13,14]. 
[1,12,13,14,4,5] #Final list after running the code. 

कुछ इस उत्तर के लिए इस्तेमाल किया संदर्भ: की तरह अगर यह एक एनीमेशन फ्रेम था तो यह आसान है व्याख्या करने के लिए

problemList = [1, [2, 3, 4], 5] 
problemList[1:2] = problemList[1] #The same as problemList[1:2] = [2,3,4] 
analogProblemL = [1] + [2,3,4] + [5] #Output : [1,2,3,4,5] 

insertList = [12,13,14] 
myList = [1, [2, 3, 4], 5,6,7,8,9] 
myList[3:6] = insertList 
analogFstList = [1,[2,3,4] ,5] + insertList + [9] #Output : [1,[2,3,4],5,12,13,14,9] 

myScnList = [1, [2, 3, 4], 5] 
myScnList[1:3] = [2,3,4] 
analogScnList = [1] + [2,3,4] + [5] #Output : [1,2,3,4,5] 

अगली पंक्तियों में हो जाएगा यह आपके लिए उपयोगी था।

1

आप यहां क्या प्रयास कर रहे हैं उसे स्लाइस आकलन कहा जाता है। पायथन में एक अन्य पुनरावर्तनीय (my_list[0:1] आपके मामले में) के एक टुकड़े के लिए एक पुनरावर्तनीय (my_list[1] अपने मामले में) असाइन करना संभव है। कुछ उदाहरण के माध्यम से चलना देता है समझने के लिए यह वास्तव में मतलब है:

>>> l = [1,2,3,4,5] 
>>> b = [6,7,8] 
>>> l[0:3] = b 
>>> l 
>>> [6, 7, 8, 4, 5] 

तो 0,1,2 सूचकांक के लिए सूची l के भाग यहाँ क्या हुआ है जो तत्वों 1,2,3 सूची b6,7,8 के तत्वों की जगह शामिल किया गया है। हालांकि इस मामले में स्लाइस का आकार और प्रतिस्थापित तत्व मौके के बराबर होते हैं।

तो क्या होता है जब टुकड़ा आकार और iterable प्रतिस्थापित करने की बजाय, यह सिर्फ कॉपी किया जो कुछ तत्वों पूरे कटा हुआ भाग के साथ उपलब्ध हैं, बराबर

>>> l = [1,2,3,4,5] 
>>> b = [6,7,8] 
>>> l[0:4] = b 
>>> l 
>>> [6,7,8,5] 

सूचना है कि इस आपरेशन किसी भी त्रुटि नहीं मिला नहीं हैं । इस मामले में, कटा हुआ तत्व 1,2,3,46,7,8

पिछले उदाहरण में प्रतिस्थापित करने योग्य इसे छोटा था।यदि टुकड़ा भाग छोटे

>>> l = [1,2,3,4,5] 
>>> b = [6,7,8] 
>>> l[0:1] = b 
>>> l 
>>> [6,7,8,2,3,4,5] 

तो अब हम देख सकते हैं कि केवल पहला तत्व पूरे iterable b ने ले ली है, तो क्या होगा।

आप इस व्यवहार का उपयोग सूची के एक विशिष्ट भाग को हटाने के लिए भी कर सकते हैं (जिसे मुझे कुछ स्थितियों में सुविधाजनक लगता है)।

>>> l = [1,2,3,4,5] 
>>> l[0:2] = [] 
>>> l 
>>> [3,4,5] 

पहले दो तत्व यहां आसानी से हटा दिए जाते हैं।

तो आपके प्रश्न में उदाहरण ऊपर दिए गए उदाहरणों के समान है, सिवाय इसके कि आपके मामले में अनपॅकिंग सूची मान का एक अतिरिक्त चरण है। अनपॅकिंग सूची मूल्य हर बार होता है जब आप किसी अन्य सूची में सूची असाइन करते हैं। एक छोटी उदाहरण

>>> l = [[1]] 
>>> a = [] 
>>> a = l[0] 
>>> a 
>>> [1] 

आपका उदाहरण अब:

#Replace the slice [0:1] with my_list[1] perform unpacking list values as well 
>>> my_list[1:2] = my_list[1] 
>>> [1,2,3,4,5] 

भी ध्यान रखें कि टुकड़ा काम तभी संभव है यदि आप iterable एक टुकड़ा करने के लिए आवंटित। यदि आप एक इंट या कुछ असाइन करने का प्रयास करते हैं जो एक टुकड़ा पायथन के लिए एक पुनरावर्तनीय नहीं है तो एक त्रुटि फेंक देगा।

>>> l = [1,2,3,4,5] 
>>> b = [6,7,8] 
>>> l[0:1] = b[1] 
>>> Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: can only assign an iterable 

है कि क्योंकि यह एक iterable यही कारण है कि अपने मामले my_list[1] में कोई त्रुटि नहीं उठता।

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