पाइथन में कोई तुच्छ समझ क्यों नहीं है?


339

जैसा कि हम सभी जानते हैं, सूची की समझ है, जैसे

[i for i in [1, 2, 3, 4]]

और शब्दकोश समझ है, जैसे

{i:j for i, j in {1: 'a', 2: 'b'}.items()}

परंतु

(i for i in (1, 2, 3))

एक जनरेटर में खत्म हो जाएगा, एक tupleसमझ नहीं है । ऐसा क्यों है?

मेरा अनुमान है कि tupleयह अपरिवर्तनीय है, लेकिन इसका उत्तर नहीं लगता है।


15
वहाँ भी एक सेट समझ है - जो एक
तानाशाही

3
आपके कोड में एक सिंटैक्स त्रुटि है: {i:j for i,j in {1:'a', 2:'b'}}होना चाहिए{i:j for i,j in {1:'a', 2:'b'}.items()}
इनबार रोज

@ InbarRose इसे इंगित करने के लिए धन्यवाद।
Shady Xu

बस पद के लिए, पायथन चैट
इनबार रोज

जाहिर है वहाँ है stackoverflow.com/a/51811147/9627166
सुपर एस

जवाबों:


470

आप एक जनरेटर अभिव्यक्ति का उपयोग कर सकते हैं:

tuple(i for i in (1, 2, 3))

लेकिन ... कोष्ठक पहले से ही ... के लिए लिया गया था।


15
इस तर्क से, हम कह सकते हैं कि एक सूची-समझ भी अनावश्यक है list(i for i in (1,2,3)):। मुझे वास्तव में लगता है कि यह सिर्फ इसलिए है क्योंकि इसके लिए एक साफ वाक्यविन्यास नहीं है (या कम से कम किसी ने भी एक के बारे में नहीं सोचा है)
mgilson

79
एक जनरेटर अभिव्यक्ति का उपयोग करने के लिए एक सूची या सेट या तानाशाह समझ बस चीनी है कि एक विशिष्ट प्रकार का उत्पादन करता है। list(i for i in (1, 2, 3))एक जनरेटर अभिव्यक्ति है जो एक सूची का उत्पादन करती है,set(i for i in (1, 2, 3)) आउटपुट करता है एक सेट को आउटपुट करता है। इसका मतलब यह है कि समझ वाक्य रचना की जरूरत नहीं है? शायद नहीं, लेकिन यह बहुत आसान है। दुर्लभ मामलों के लिए आपको इसके बजाय एक टपल की आवश्यकता होती है, जनरेटर अभिव्यक्ति करेगा, स्पष्ट है, और दूसरे ब्रेस या ब्रैकेट के आविष्कार की आवश्यकता नहीं है।
मार्टिज़न पीटरर्स

16
जवाब स्पष्ट रूप से है क्योंकि टुपल सिंटैक्स और कोष्ठक अस्पष्ट हैं
चार्ल्स साल्विया

19
यदि आप प्रदर्शन की परवाह करते हैं तो एक कंस्ट्रक्शन का उपयोग करने और एक कंस्ट्रक्टर + जनरेटर का उपयोग करने के बीच का अंतर सूक्ष्म से अधिक है। एक निर्माणकर्ता को दिए गए जनरेटर का उपयोग करने की तुलना में तेजी से निर्माण में परिणाम होता है। बाद के मामले में आप पायथन में कार्यों और कार्यों को महंगा कर रहे हैं और निष्पादित कर रहे हैं। [thing for thing in things]की तुलना में बहुत तेजी से एक सूची बनाता है list(thing for thing in things)। एक तुच्छ समझ बेकार नहीं होगी; tuple(thing for thing in things)विलंबता मुद्दों और हैtuple([thing for thing in things]) स्मृति समस्याएँ हो सकती हैं।
जस्टिन टर्नर आर्थर

9
@MartijnPieters, क्या आप संभावित रूप से पुनर्मुद्रण कर सकते हैं A list or set or dict comprehension is just syntactic sugar to use a generator expression? यह पैदा भ्रम के रूप में इन देखकर लोगों द्वारा बराबर एक को समाप्त करने का मतलब है। यह तकनीकी रूप से सिंथेटिक चीनी नहीं है क्योंकि प्रक्रियाएं वास्तव में अलग हैं, भले ही अंतिम उत्पाद समान हो।
जेपी

77

रेमंड हेटिंगर (पायथन कोर डेवलपर्स में से एक) ने हाल के एक ट्वीट में ट्यूपल्स के बारे में कहा था :

# खट्टा टिप: आम तौर पर, सूचियां लूपिंग के लिए होती हैं; संरचना के लिए tuples। सूची सजातीय हैं; टुपल्स विषम। चर लंबाई के लिए सूची।

यह (मेरे लिए) इस विचार का समर्थन करता है कि यदि किसी क्रम में आइटम पर्याप्त रूप से संबंधित होने के लिए ए, कुएं, जनरेटर द्वारा उत्पन्न होते हैं, तो यह एक सूची होनी चाहिए। यद्यपि एक ट्यूलल चलने योग्य है और बस एक अपरिवर्तनीय सूची की तरह लगता है, यह वास्तव में एक सी संरचना के पायथन के बराबर है:

struct {
    int a;
    char b;
    float c;
} foo;

struct foo x = { 3, 'g', 5.9 };

अजगर में हो जाता है

x = (3, 'g', 5.9)

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

रेमंड हेटिंगर से एक अच्छी टिप। मैं अभी भी कहूंगा कि एक जनरेटर के साथ टपल कंस्ट्रक्टर का उपयोग करने के लिए एक उपयोग मामला है, जैसे कि एक और संरचना को खोलना, शायद बड़ा, एक छोटे से एक में अटेटर्स पर पुनरावृति करके जो आप एक ट्यूपर रिकॉर्ड को परिवर्तित करने में रुचि रखते हैं।
डेव

2
@ आप शायद केवल operator.itemgetterउस मामले में उपयोग कर सकते हैं ।
chepner

@ शेपनर, मैं देख रहा हूं। इसका मतलब है कि मैं बहुत करीब हूं। यह एक कॉल करने योग्य लौटाता है, अगर मुझे केवल एक बार जीतना है, तो मुझे tuple(obj[item] for item in items)सीधे जीत का उपयोग करने की आवश्यकता नहीं है। मेरे मामले में मैं इस सूची में एक रिकॉर्ड बनाने की कोशिश कर रहा था, जो टपल रिकॉर्डों की एक सूची बना रहा था। अगर मुझे पूरे कोड में बार-बार ऐसा करने की आवश्यकता है तो आइटमगेटर बहुत अच्छा लगता है। शायद आइटमग्रेटर या तो अधिक मुहावरेदार होगा?
डेव

मैं फ्रेंजेनसेट के बीच संबंध देखता हूं और टपल और सूची के अनुरूप होता हूं। यह विषमता के बारे में कम है और अपरिवर्तनीयता के बारे में अधिक है - फ्रोज़ेन्सेट्स और टुपल्स शब्दकोशों, सूचियों की कुंजी हो सकते हैं और उनकी पारस्परिकता के कारण सेट नहीं हो सकते हैं।
बहुवचन

56

पाइथन 3.5 के बाद से , आप *जनरेटर एक्सर्साइज को अनपैक करने के लिए स्प्लैट अनपैकिंग सिंटैक्स का भी उपयोग कर सकते हैं :

*(x for x in range(10)),

2
यह बहुत अच्छा है (और यह काम करता है), लेकिन मुझे कहीं भी यह दस्तावेज नहीं मिला है! क्या आपके पास एक लिंक है?
felixphew

8
नोट: कार्यान्वयन विवरण के रूप में, यह मूल रूप से करने के समान है tuple(list(x for x in range(10)))( कोड पथ समान हैं , दोनों एक listसाथ निर्माण करते हैं , एकमात्र अंतर यह है कि अंतिम चरण tupleसे एक आउटपुट बनाना है listऔर listजब tupleआउटपुट होता है तब इसे फेंक देना चाहिए आवश्यक है)। इसका मतलब है कि आप वास्तव में अस्थायी लोगों की एक जोड़ी से नहीं बचते हैं।
शैडो रेंजर

4
@ShadowRanger की टिप्पणी पर विस्तार करने के लिए, यहाँ एक प्रश्न है जहाँ वे दिखाते हैं कि स्प्लट + टुपल शाब्दिक सिंटैक्स वास्तव में टुपल कंस्ट्रक्टर के लिए एक जनरेटर अभिव्यक्ति पास करने की तुलना में काफी धीमा है।
ल्यूसुब्रेटर

मैं पायथन 3.7.3 में यह कोशिश कर रहा हूँ और *(x for x in range(10))काम नहीं करता है। मुझे मिलता है SyntaxError: can't use starred expression here। हालांकि tuple(x for x in range(10))काम करता है।
रयान एच।

4
@RyanH। आपको अंत में अल्पविराम लगाने की आवश्यकता है।
czheo

27

एक और पोस्टर के रूप में macm उल्लेख किया गया है, एक जनरेटर से टपल बनाने का सबसे तेज़ तरीका है tuple([generator])


प्रदर्शन की तुलना

  • सूची की समझ:

    $ python3 -m timeit "a = [i for i in range(1000)]"
    10000 loops, best of 3: 27.4 usec per loop
  • सूची समझ से बाहर निकलें:

    $ python3 -m timeit "a = tuple([i for i in range(1000)])"
    10000 loops, best of 3: 30.2 usec per loop
  • जनरेटर से टपल:

    $ python3 -m timeit "a = tuple(i for i in range(1000))"
    10000 loops, best of 3: 50.4 usec per loop
  • अनपैकिंग से ट्यूपल:

    $ python3 -m timeit "a = *(i for i in range(1000)),"
    10000 loops, best of 3: 52.7 usec per loop

अजगर का मेरा संस्करण :

$ python3 --version
Python 3.6.3

इसलिए आपको हमेशा एक सूची समझ से एक टपल बनाना चाहिए जब तक कि प्रदर्शन कोई समस्या नहीं है।


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

25

टंकियों पर लूपिंग या पुनरावृति करके और उन्हें कंटेनर में असाइन करके, टुपल असाइनमेंट प्राप्त करने में असमर्थ है।

एक बार टपल बनने के बाद, इसे जोड़ा, बढ़ाया या सौंपा नहीं जा सकता है। टपल को संशोधित करने का एकमात्र तरीका यह है कि इसकी एक वस्तु को खुद को सौंपा जा सकता है (एक गैर-टपल कंटेनर है)। क्योंकि टपल केवल उस तरह की वस्तु का संदर्भ रखता है।

इसके अलावा - एक टपल का अपना कंस्ट्रक्टर है tuple()जिसे आप कोई भी इटेरेटर दे सकते हैं। जिसका मतलब है कि एक टपल बनाने के लिए, आप यह कर सकते हैं:

tuple(i for i in (1,2,3))

9
कुछ मायनों में मैं सहमत हूं (इस बारे में आवश्यक नहीं है क्योंकि एक सूची होगी), लेकिन अन्य तरीकों से मैं असहमत हूं (तर्क के बारे में क्योंकि यह अपरिवर्तनीय है)। कुछ मायनों में, यह अपरिवर्तनीय वस्तुओं के लिए एक समझ रखने के लिए अधिक समझ में आता है। कौन करता है lst = [x for x in ...]; x.append()?
mgilson

@mgilson मुझे यकीन नहीं है कि जो मैंने कहा था उससे कैसे संबंधित है?
इबार रोज

2
@mgilson यदि एक टूपल अपरिवर्तनीय है जिसका अर्थ है कि अंतर्निहित कार्यान्वयन एक टपल को उत्पन्न नहीं कर सकता है ("जेनरेशन" जो एक समय में एक टुकड़े का निर्माण कर रहा है)। अपरिवर्तनीय का मतलब है कि आप 4 टुकड़ों में से एक को 3 टुकड़ों के साथ बदलकर निर्माण नहीं कर सकते। इसके बजाय, आप एक सूची बनाकर टपल "जनरेशन" को लागू करते हैं, पीढ़ी के लिए डिज़ाइन की गई कोई चीज़, फिर टपल को अंतिम चरण के रूप में बनाते हैं, और सूची को छोड़ देते हैं। भाषा इस वास्तविकता को दर्शाती है। सी संरचना के रूप में टुपल्स के बारे में सोचें।
स्कॉट

2
हालांकि यह टुपल्स के लिए काम करने के लिए समझ के चीनी के लिए उचित होगा, क्योंकि आप तब तक टपल का उपयोग नहीं कर सकते जब तक कि कॉम्प्रिहेंशन वापस न हो जाए। प्रभावी रूप से यह उत्परिवर्तित की तरह कार्य नहीं करता है, बल्कि एक तुच्छ समझ अधिक कठोर स्ट्रिंग की तरह व्यवहार कर सकता है।
uchuugaka

12

मेरा सबसे अच्छा अनुमान है कि वे कोष्ठक से बाहर भाग गए और ऐसा नहीं लगा कि यह एक "बदसूरत" वाक्यविन्यास को जोड़ने के लिए पर्याप्त उपयोगी होगा ...


1
कोण कोष्ठक अप्रयुक्त।
uchuugaka

@ यूचुगाका - पूरी तरह से नहीं। वे तुलना ऑपरेटरों के लिए उपयोग किया जाता है। यह शायद अभी भी अस्पष्टता के बिना किया जा सकता है, लेकिन शायद प्रयास के लायक नहीं ...
mgilson

3
@ यूचुगाका वर्थ {*()}, हालांकि, बदसूरत, एक खाली सेट शाब्दिक के रूप में काम करता है!
एमआई राइट

1
ओह। सौंदर्य के दृष्टिकोण से, मुझे लगता है कि मैं आंशिक हूं set():)
mgilson

1
@QuantumMechanic: हाँ, यह बात है; अनपैकेजिंग सामान्यीकरण ने खाली "सेट शाब्दिक" को संभव बनाया। ध्यान दें कि {*[]}अन्य विकल्पों में कड़ाई से हीनता है; खाली स्ट्रिंग और खाली tuple, अपरिवर्तनीय होते हैं, सिंगलटन होते हैं, इसलिए खाली निर्माण के लिए किसी अस्थायी की आवश्यकता नहीं होती है set। इसके विपरीत, खाली listएक सिंगलटन नहीं है, इसलिए आपको वास्तव में इसका निर्माण करना होगा, इसे बनाने के लिए उपयोग करना होगा set, फिर इसे नष्ट करना होगा, जो भी तुच्छ प्रदर्शन एक आंख वाले बंदर ऑपरेटर को प्रदान करता है उसे खो देता है।
शैडो रेंजर

8

Tuples कुशलता से एक सूची की तरह संलग्न नहीं किया जा सकता है।

इसलिए एक वृहद समझ को आंतरिक रूप से एक सूची का उपयोग करने और फिर एक टुपल में बदलने की आवश्यकता होगी।

यह वही होगा जो आप अभी करते हैं: टपल ([समझ])


3

कोष्ठक एक टपल नहीं बनाते हैं। उर्फ एक = (दो) टपल नहीं है। चारों ओर एकमात्र रास्ता या तो एक = (दो,) या एक = टपल (दो) है। तो एक समाधान है:

tuple(i for i in myothertupleorlistordict) 

अच्छा। यह लगभग समान है।
uchuugaka

-1

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


-2

हम सूची बोध से टुपल्स उत्पन्न कर सकते हैं। निम्न में से दो संख्याओं को क्रमिक रूप से एक टुपल में जोड़ा जाता है और संख्या 0-9 से एक सूची देता है।

>>> print k
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
>>> r= [tuple(k[i:i+2]) for i in xrange(10) if not i%2]
>>> print r
[(0, 1), (2, 3), (4, 5), (6, 7), (8, 9)]
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.