2016-10-24 24 views
55

set फ़ंक्शन कॉल डुप्लीस को क्यों मिटा देता है, लेकिन एक सेट शाब्दिक पार्सिंग नहीं करता है?सेट सेट फ़ंक्शन कॉल से अलग परिणाम देता है

>>> x = Decimal('0') 
>>> y = complex(0,0) 
>>> set([0, x, y]) 
{0} 
>>> {0, x, y} 
{Decimal('0'), 0j} 

(this समान प्रश्न के लिए के रूप में अजगर 2.7.12। संभवत: एक ही मूल कारण) समानता के लिए

+0

संबंधित: [Dict/सेट पार्सिंग आदेश संगति] (https://stackoverflow.com/q/34623846/4279) – jfs

उत्तर

53

सेट परीक्षण, और जब तक वहाँ नए अजगर रिलीज कर रहे हैं, जिस क्रम में वे करते हैं इस आधार पर अलग-अलग हो सकते हैं फॉर्म पर आप मूल्यों को सेट पर सेट कर सकते हैं, जैसा कि मैं नीचे दिखाऊंगा।

0 == x के बाद से सच है और0 == y सही है, लेकिन x == yझूठी है, व्यवहार यहाँ वास्तव में अपरिभाषित के रूप में सेट मानता है कि x == y सच होना चाहिए अगर पहले दो परीक्षण भी सही थे है।

यदि आप रिवर्स सूची set() को पारित कर दिया है, तो आप एक शाब्दिक का उपयोग कर के रूप में ही उत्पादन, मिलता है क्योंकि समानता के आदेश परिवर्तनों का परीक्षण करता:

>>> set([y, x, 0]) 
set([0j, Decimal('0')]) 

और शाब्दिक को पलटने के लिए एक ही:

>>> {y, x, 0} 
set([0]) 

क्या हो रहा है यह है कि सेट शाब्दिक भार मूल्यों ढेर पर और फिर ढेर मूल्यों नया सेट वस्तु से जुड़ जाते हैं उल्टे क्रम में।

जब तक 0 भरी हुई है पहले, अन्य दो वस्तुओं तो 0 के खिलाफ पहले से ही सेट में जांच की जाती है। पल दो अन्य वस्तुओं में से एक पहले भरी हुई है, समानता परीक्षण विफल रहता है और आप दो वस्तुओं जोड़ा मिलती है:

>>> {y, 0, x} 
set([Decimal('0'), 0j]) 
>>> {x, 0, y} 
set([0j, Decimal('0')]) 

सेट कि शाब्दिक रिवर्स में तत्वों को जोड़ने कि वाक्य रचना का समर्थन पायथन के सभी संस्करणों में एक बग मौजूद है , पाइथन 2.7.12 और 3.5.2 तक सभी तरह से। इसे हाल ही में तय किया गया था, issue 26020 देखें (2.7.13, 3.5.3 और 3.6 का हिस्सा, इनमें से कोई भी अभी तक जारी नहीं किया गया है)। आप 2.7.12 को देखें, तो आप देख सकते हैं कि BUILD_SET in ceval.c शीर्ष नीचे से ढेर पढ़ता है:

# oparg is the number of elements to take from the stack to add 
for (; --oparg >= 0;) { 
    w = POP(); 
    if (err == 0) 
     err = PySet_Add(x, w); 
    Py_DECREF(w); 
} 

जबकि बाईटकोड उलटे क्रम में ढेर करने के लिए तत्वों कहते हैं (पहली स्टैक पर 0 धक्का):

>>> from dis import dis 
>>> dis(compile('{0, x, y}', '', 'eval')) 
    2   0 LOAD_CONST    1 (0) 
       3 LOAD_GLOBAL    0 (x) 
       6 LOAD_GLOBAL    1 (y) 
       9 BUILD_SET    3 
      12 RETURN_VALUE 

फिक्स स्टैक से तत्वों को रिवर्स ऑर्डर में पढ़ने के लिए है; Python 2.7.13 version का उपयोग करता PEEK() बजाय POP() (और एक STACKADJ() ढेर से तत्वों बाद में दूर करने के लिए):

for (i = oparg; i > 0; i--) { 
    w = PEEK(i); 
    if (err == 0) 
     err = PySet_Add(x, w); 
    Py_DECREF(w); 
} 
STACKADJ(-oparg); 

समानता परीक्षण मुद्दा अन्य प्रश्न के रूप में ही मूल कारण है; Decimal() कक्षा में complex के साथ कुछ समानताएं समस्याएं हैं, जिन्हें पायथन 3.2 में तय किया गया था (Decimal() support comparisons to complex and a few other numeric types it didn't support before बनाकर)।

+10

आपको लगता है यह एक बग है कि समानता इन तीन प्रकार के लिए सकर्मक नहीं है है? –

+7

@StevenRumbalski: मुझे ऐसा लगता है, हाँ। '0j' 'दशमलव (' 0 ') के बराबर क्यों नहीं होना चाहिए, जब' 0j == 0' सत्य है और 'दशमलव (' 0 ') == 0' भी सत्य है। पायथन 3.2 ने 'दशमलव 'तुलना को अद्यतन करके इसे ठीक किया। –

+2

'bytearray ('ab') == 'ab' == u'ab' भी पारगमनशीलता तोड़ रहा है, लेकिन चूंकि 'bytearray' को अक्षम नहीं किया गया है, इसका कोई परिणाम नहीं है। – wim

7

यह सेट उस क्रम में है जिस पर सेट बनाया गया है, जिसे आपने your other question के साथ खोजे गए बग के साथ जोड़ा है। ऐसा लगता है कि एक सूची से रूपांतरण के लिए शाब्दिक क्रम में बनाया गया है।

>>> {0, x, y} 
set([0j, Decimal('0')]) 
>>> {y, x, 0} 
set([0]) 
+0

आह, हाँ यह अंतर्दृष्टिपूर्ण है। एक cpython स्रोत संदर्भ के बारे में कैसे दिखाता है कि कैसे शाब्दिक दाएं से बाएं पार्स किया जाता है? – wim

+0

@ विम: मुझे इसके लिए कोड ढूंढने में परेशानी थी, केवल इसलिए कि बग हाल ही में तय किया गया था। –

+0

@wim जैसा लगता है कि मजेदार है, मैं कभी भी पायथन स्रोत कोड के माध्यम से spelunking नहीं चला गया है। –

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