अनपैकिंग, विस्तारित अनपैकिंग और नेस्टेड विस्तारित अनपैकिंग


105

निम्नलिखित भावों पर विचार करें। ध्यान दें कि कुछ अभिव्यक्तियों को "संदर्भ" प्रस्तुत करने के लिए दोहराया जाता है।

(यह एक लंबी सूची है)

a, b = 1, 2                          # simple sequence assignment
a, b = ['green', 'blue']             # list asqignment
a, b = 'XY'                          # string assignment
a, b = range(1,5,2)                  # any iterable will do


                                     # nested sequence assignment

(a,b), c = "XY", "Z"                 # a = 'X', b = 'Y', c = 'Z' 

(a,b), c = "XYZ"                     # ERROR -- too many values to unpack
(a,b), c = "XY"                      # ERROR -- need more than 1 value to unpack

(a,b), c, = [1,2],'this'             # a = '1', b = '2', c = 'this'
(a,b), (c,) = [1,2],'this'           # ERROR -- too many values to unpack


                                     # extended sequence unpacking

a, *b = 1,2,3,4,5                    # a = 1, b = [2,3,4,5]
*a, b = 1,2,3,4,5                    # a = [1,2,3,4], b = 5
a, *b, c = 1,2,3,4,5                 # a = 1, b = [2,3,4], c = 5

a, *b = 'X'                          # a = 'X', b = []
*a, b = 'X'                          # a = [], b = 'X'
a, *b, c = "XY"                      # a = 'X', b = [], c = 'Y'
a, *b, c = "X...Y"                   # a = 'X', b = ['.','.','.'], c = 'Y'

a, b, *c = 1,2,3                     # a = 1, b = 2, c = [3]
a, b, c, *d = 1,2,3                  # a = 1, b = 2, c = 3, d = []

a, *b, c, *d = 1,2,3,4,5             # ERROR -- two starred expressions in assignment

(a,b), c = [1,2],'this'              # a = '1', b = '2', c = 'this'
(a,b), *c = [1,2],'this'             # a = '1', b = '2', c = ['this']

(a,b), c, *d = [1,2],'this'          # a = '1', b = '2', c = 'this', d = []
(a,b), *c, d = [1,2],'this'          # a = '1', b = '2', c = [], d = 'this'

(a,b), (c, *d) = [1,2],'this'        # a = '1', b = '2', c = 't', d = ['h', 'i', 's']

*a = 1                               # ERROR -- target must be in a list or tuple
*a = (1,2)                           # ERROR -- target must be in a list or tuple
*a, = (1,2)                          # a = [1,2]
*a, = 1                              # ERROR -- 'int' object is not iterable
*a, = [1]                            # a = [1]
*a = [1]                             # ERROR -- target must be in a list or tuple
*a, = (1,)                           # a = [1]
*a, = (1)                            # ERROR -- 'int' object is not iterable

*a, b = [1]                          # a = [], b = 1
*a, b = (1,)                         # a = [], b = 1

(a,b),c = 1,2,3                      # ERROR -- too many values to unpack
(a,b), *c = 1,2,3                    # ERROR - 'int' object is not iterable
(a,b), *c = 'XY', 2, 3               # a = 'X', b = 'Y', c = [2,3]


                                     # extended sequence unpacking -- NESTED

(a,b),c = 1,2,3                      # ERROR -- too many values to unpack
*(a,b), c = 1,2,3                    # a = 1, b = 2, c = 3

*(a,b) = 1,2                         # ERROR -- target must be in a list or tuple
*(a,b), = 1,2                        # a = 1, b = 2

*(a,b) = 'XY'                        # ERROR -- target must be in a list or tuple
*(a,b), = 'XY'                       # a = 'X', b = 'Y'

*(a, b) = 'this'                     # ERROR -- target must be in a list or tuple
*(a, b), = 'this'                    # ERROR -- too many values to unpack
*(a, *b), = 'this'                   # a = 't', b = ['h', 'i', 's']

*(a, *b), c = 'this'                 # a = 't', b = ['h', 'i'], c = 's'

*(a,*b), = 1,2,3,3,4,5,6,7           # a = 1, b = [2, 3, 3, 4, 5, 6, 7]

*(a,*b), *c = 1,2,3,3,4,5,6,7        # ERROR -- two starred expressions in assignment
*(a,*b), (*c,) = 1,2,3,3,4,5,6,7     # ERROR -- 'int' object is not iterable
*(a,*b), c = 1,2,3,3,4,5,6,7         # a = 1, b = [2, 3, 3, 4, 5, 6], c = 7
*(a,*b), (*c,) = 1,2,3,4,5,'XY'      # a = 1, b = [2, 3, 4, 5], c = ['X', 'Y']

*(a,*b), c, d = 1,2,3,3,4,5,6,7      # a = 1, b = [2, 3, 3, 4, 5], c = 6, d = 7
*(a,*b), (c, d) = 1,2,3,3,4,5,6,7    # ERROR -- 'int' object is not iterable
*(a,*b), (*c, d) = 1,2,3,3,4,5,6,7   # ERROR -- 'int' object is not iterable
*(a,*b), *(c, d) = 1,2,3,3,4,5,6,7   # ERROR -- two starred expressions in assignment


*(a,b), c = 'XY', 3                  # ERROR -- need more than 1 value to unpack
*(*a,b), c = 'XY', 3                 # a = [], b = 'XY', c = 3
(a,b), c = 'XY', 3                   # a = 'X', b = 'Y', c = 3

*(a,b), c = 'XY', 3, 4               # a = 'XY', b = 3, c = 4
*(*a,b), c = 'XY', 3, 4              # a = ['XY'], b = 3, c = 4
(a,b), c = 'XY', 3, 4                # ERROR -- too many values to unpack

हाथ से ऐसे भावों के परिणाम को सही ढंग से कैसे घटाया जाए?


28
ईमानदारी से, इनमें से अधिकांश हर उस चीज़ से कहीं अधिक जटिल हैं जो आप हर रोज़ कोड में देखते हैं। अनपैकिंग लिस्ट / ट्यूपल्स की मूल बातें जानें और आप ठीक रहेंगे।
राफे केटलर

2
ध्यान दें कि ये पुनरावर्ती हैं। इसलिए, यदि आप पहले कुछ को रेखांकित करते हैं, तो आप सब कुछ संभाल सकते हैं। प्रतिस्थापित करने का प्रयास करें, जैसे, *, * (* a, b) के साथ * x, यह पता लगाएँ कि क्या x अनपैक्स और फिर प्लग (* a, b) वापस x के लिए, आदि
पीटरिस

4
@greengit मैं अपने आप को पायथन का एक उन्नत ज्ञान मानता हूं और मैं सिर्फ सामान्य नियमों को जानता हूं :) आपको हर कोने के मामले को जानने की जरूरत नहीं है, आपको बस कभी-कभी एक दुभाषिया को आग लगाने और कुछ का परीक्षण करने की आवश्यकता है।
राफे केटलर

वाह बढ़िया सूची। मैं वास्तव a, *b = 1, 2, 3में अनपैकिंग के प्रकार के बारे में नहीं जानता था । लेकिन यह Py3k सही है?
निकल्स आर

जवाबों:


113

इस पद की लंबाई के लिए मेरी माफी, लेकिन मैंने पूर्णता का विकल्प चुनने का फैसला किया।

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

केवल अनपैकिंग के प्रयोजनों के लिए, निम्नलिखित प्रतिस्थापन दाईं ओर =(यानी प्रतिद्वंद्वियों के लिए ) मान्य हैं :

'XY' -> ('X', 'Y')
['X', 'Y'] -> ('X', 'Y')

यदि आप पाते हैं कि कोई मान नहीं मिला है, तो आप प्रतिस्थापन को पूर्ववत कर देंगे। (आगे की व्याख्या के लिए नीचे देखें।)

इसके अलावा, जब आप "नग्न" कॉमा देखते हैं, तो दिखाते हैं कि एक शीर्ष स्तरीय टपल है। इसे बाईं और दाईं ओर (दोनों के बीच में अंतराल और अंतराल के लिए ) करें:

'X', 'Y' -> ('X', 'Y')
a, b -> (a, b)

उन सरल नियमों को ध्यान में रखते हुए, यहां कुछ उदाहरण दिए गए हैं:

(a,b), c = "XY", "Z"                 # a = 'X', b = 'Y', c = 'Z'

उपरोक्त नियमों को लागू करते हुए, हम पार्न में नग्न अल्पविरामों "XY"को परिवर्तित ('X', 'Y')और कवर करते हैं:

((a, b), c) = (('X', 'Y'), 'Z')

यहाँ दृश्य पत्राचार यह काफी स्पष्ट करता है कि असाइनमेंट कैसे काम करता है।

यहाँ एक गलत उदाहरण है:

(a,b), c = "XYZ"

उपरोक्त प्रतिस्थापन नियमों का पालन करते हुए, हम नीचे दिए गए हैं:

((a, b), c) = ('X', 'Y', 'Z')

यह स्पष्ट रूप से गलत है; नेस्टेड संरचनाएं मेल नहीं खाती हैं। अब देखते हैं कि यह कैसे अधिक जटिल उदाहरण के लिए काम करता है:

(a,b), c, = [1,2],'this'             # a = '1', b = '2', c = 'this'

उपरोक्त नियमों को लागू करते हुए, हम प्राप्त करते हैं

((a, b), c) = ((1, 2), ('t', 'h', 'i', 's'))

लेकिन अब यह उस संरचना से स्पष्ट है जिसे 'this'अनपैक नहीं किया जाएगा, बल्कि सीधे इसे सौंपा जाएगा c। इसलिए हम प्रतिस्थापन को पूर्ववत करते हैं।

((a, b), c) = ((1, 2), 'this')

अब देखते हैं कि जब हम cएक ट्यूल में लपेटते हैं तो क्या होता है :

(a,b), (c,) = [1,2],'this'           # ERROR -- too many values to unpack

हो जाता है

((a, b), (c,)) = ((1, 2), ('t', 'h', 'i', 's'))

फिर, त्रुटि स्पष्ट है। cअब एक नग्न चर नहीं है, लेकिन एक अनुक्रम के अंदर एक चर है, और इसलिए दाईं ओर इसी क्रम को अनपैक किया गया है (c,)। लेकिन दृश्यों की एक अलग लंबाई है, इसलिए एक त्रुटि है।

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

a, *b, c = "X...Y"                   # a = 'X', b = ['.','.','.'], c = 'Y'

यह बन जाता है

(a, *b, c) = ('X', '.', '.', '.', 'Y')

इसका विश्लेषण करने का सबसे सरल तरीका सिरों से काम करना है। 'X'को सौंपा गया है aऔर 'Y'उसे सौंपा गया हैc । अनुक्रम के शेष मूल्यों को एक सूची में रखा गया है और उन्हें सौंपा गया हैb

जैसे Lvalues (*a, b)और (a, *b)इसके बाद के संस्करण का सिर्फ विशेष मामले हैं। आपके पास *एक लैवल्यू सीक्वेंस के अंदर दो ऑपरेटर नहीं हो सकते क्योंकि यह अस्पष्ट होगा। मूल्य कुछ इस तरह से कहाँ जाएंगे (a, *b, *c, d)- bया में c? मैं एक क्षण में नेस्टेड मामले पर विचार करूंगा।

*a = 1                               # ERROR -- target must be in a list or tuple

यहाँ त्रुटि काफी आत्म-व्याख्यात्मक है। लक्ष्य ( *a) टपल में होना चाहिए।

*a, = (1,2)                          # a = [1,2]

यह काम करता है क्योंकि वहाँ एक नग्न अल्पविराम है। नियम लागू करना ...

(*a,) = (1, 2)

चूंकि कोई अन्य की तुलना में चर रहे हैं *a, *arvalue अनुक्रम में सभी मान अप slurps। यदि आप (1, 2)एकल मान से प्रतिस्थापित करते हैं तो क्या होगा ?

*a, = 1                              # ERROR -- 'int' object is not iterable

हो जाता है

(*a,) = 1

फिर, यहाँ त्रुटि स्व-व्याख्यात्मक है। आप ऐसी किसी चीज़ को अनपैक नहीं कर सकते हैं, जो सीक्वेंस नहीं है, और *aअनपैक करने के लिए कुछ चाहिए। इसलिए हमने इसे एक क्रम में रखा

*a, = [1]                            # a = [1]

जो के लिए eqivalent है

(*a,) = (1,)

अंत में, यह भ्रम का एक सामान्य बिंदु है: (1)एक ही है 1- आपको एक अंकगणितीय कथन से टपल को अलग करने के लिए अल्पविराम की आवश्यकता है।

*a, = (1)                            # ERROR -- 'int' object is not 

अब नेस्टिंग के लिए। वास्तव में यह उदाहरण आपके "NESTED" अनुभाग में नहीं था; शायद आपको एहसास नहीं हुआ कि यह नेस्टेड था?

(a,b), *c = 'XY', 2, 3               # a = 'X', b = 'Y', c = [2,3]

हो जाता है

((a, b), *c) = (('X', 'Y'), 2, 3)

शीर्ष-स्तरीय टपल में पहला मान असाइन किया गया है, और शीर्ष-स्तरीय टपल ( 2और 3) में शेष मान cउसी तरह असाइन किए गए हैं - जैसे हमें उम्मीद करनी चाहिए।

(a,b),c = 1,2,3                      # ERROR -- too many values to unpack
*(a,b), c = 1,2,3                    # a = 1, b = 2, c = 3

मैंने पहले ही ऊपर बताया है कि पहली पंक्ति में त्रुटि क्यों होती है। दूसरी पंक्ति मूर्खतापूर्ण है लेकिन यहाँ यह क्यों काम करता है:

(*(a, b), c) = (1, 2, 3)

जैसा कि पहले बताया गया है, हम सिरों से काम करते हैं। 3को सौंपा गया है c, और फिर शेष मूल्यों के साथ चर के लिए आवंटित कर रहे हैं *, यह पूर्ववर्ती, इस मामले में (a, b)। तो इसके बराबर है (a, b) = (1, 2), जो काम करने के लिए होता है क्योंकि तत्वों की सही संख्या होती है। मैं किसी भी कारण के बारे में सोच नहीं सकता है जो कभी भी काम करने वाले कोड में दिखाई देगा। इसी तरह,

*(a, *b), c = 'this'                 # a = 't', b = ['h', 'i'], c = 's'

हो जाता है

(*(a, *b), c) = ('t', 'h', 'i', 's')

सिरों से कार्य करना, 's'को सौंपा गया है cऔर ('t', 'h', 'i')उसे सौंपा गया है (a, *b)। छोर से फिर से काम करते हुए, 't'को सौंपा गया है a, और ('h', 'i')एक सूची के रूप ख को सौंपा गया है। यह एक और मूर्खतापूर्ण उदाहरण है जिसे काम करने वाले कोड में कभी नहीं दिखाई देना चाहिए।


24
चूंकि ओपी ने एक लंबी सूची उदाहरण दी है, इसलिए यह केवल उचित है कि आप स्पष्टीकरण की एक लंबी सूची दें।
जॉन वाई

7

मुझे लगता है कि पायथन 2 टपल बहुत सीधा है। बाईं ओर का प्रत्येक नाम संपूर्ण अनुक्रम के साथ या दाईं ओर एक क्रम में एकल आइटम के साथ मेल खाता है। यदि नाम किसी भी क्रम के एकल आइटम के अनुरूप हैं, तो सभी वस्तुओं को कवर करने के लिए पर्याप्त नाम होने चाहिए।

विस्तारित अनपैकिंग, हालांकि, निश्चित रूप से भ्रमित हो सकता है, क्योंकि यह बहुत शक्तिशाली है। वास्तविकता यह है कि आपके द्वारा दिए गए अंतिम 10 या अधिक वैध उदाहरण कभी भी नहीं होने चाहिए - यदि डेटा यह है कि संरचित है, तो यह एक dictया एक श्रेणी उदाहरण में होना चाहिए , न कि सूचियों जैसे असंरचित रूपों में।

स्पष्ट रूप से, नए वाक्यविन्यास का दुरुपयोग किया जा सकता है। आपके प्रश्न का उत्तर यह है कि आपको इस तरह के भाव नहीं पढ़ने चाहिए - वे बुरे अभ्यास हैं और मुझे संदेह है कि उनका उपयोग किया जाएगा।

सिर्फ इसलिए कि आप मनमाने ढंग से जटिल अभिव्यक्ति लिख सकते हैं इसका मतलब यह नहीं है कि आपको चाहिए। आप कोड लिख सकते हैं, map(map, iterable_of_transformations, map(map, iterable_of_transformations, iterable_of_iterables_of_iterables))लेकिन आप ऐसा नहीं करते


नोट: मैंने उस तरह कोड लिखा है, कई स्तरों को छोड़कर और अधिक जटिल। यह केवल एक अभ्यास के रूप में किया गया था, और पूरे ज्ञान के साथ किया गया था कि तीन महीने बाद यह मेरे लिए व्यर्थ होगा, और यह किसी और के लिए कभी भी समझ में नहीं आएगा । यदि मुझे सही याद है, तो इसने बहुभुज परीक्षण में बिंदु को लागू किया, कुछ समन्वयित रूपांतरण किए, और कुछ SVG, HTML, और JavaScript तैयार किए।
ag

3

मुझे लगता है कि आपका कोड इसे व्यक्त करने के लिए अन्य रूप का भ्रामक उपयोग कर सकता है।

यह संचालकों के बारे में सवालों से बचने के लिए अभिव्यक्ति में अतिरिक्त कोष्ठक का उपयोग करने जैसा है। आपके कोड को पठनीय बनाने के लिए हमेशा एक अच्छा निवेश होता है।

मैं केवल स्वैप जैसे सरल कार्यों के लिए अनपैकिंग का उपयोग करना पसंद करता हूं।

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