क्या पायथन में आदेश दिए गए हैं 3.6+?


466

पिछले अवतारों के विपरीत, पायथन 3.6 (कम से कम CPython कार्यान्वयन के तहत) में आदेश दिए गए हैं। यह एक पर्याप्त बदलाव की तरह लगता है, लेकिन यह प्रलेखन में केवल एक छोटा पैराग्राफ है । इसे भाषा सुविधा के बजाय CPython कार्यान्वयन विवरण के रूप में वर्णित किया गया है, लेकिन इसका अर्थ यह भी है कि यह भविष्य में मानक बन सकता है।

तत्व आदेश को संरक्षित करते हुए नया शब्दकोश कार्यान्वयन पुराने से बेहतर प्रदर्शन कैसे करता है?

यहाँ प्रलेखन से पाठ है:

dict()अब PyPy द्वारा अग्रणी "कॉम्पैक्ट" प्रतिनिधित्व का उपयोग करता है । पायथन 3.5 की तुलना में नए तानाशाह () की मेमोरी का उपयोग 20% से 25% कम है। PEP 468 (एक समारोह में ** kwargs के आदेश का संरक्षण।) इसके द्वारा कार्यान्वित किया जाता है। इस नए कार्यान्वयन का आदेश-संरक्षण पहलू एक कार्यान्वयन विवरण माना जाता है और इस पर भरोसा नहीं किया जाना चाहिए (यह भविष्य में बदल सकता है, लेकिन यह भाषा में इस नए तानाशाही कार्यान्वयन के लिए वांछित है कि भाषा बदलने से पहले कुछ रिलीज के लिए सभी वर्तमान और भविष्य के पायथन कार्यान्वयन के लिए ऑर्डर-प्रोटेक्टिंग शब्दार्थों को अनिवार्य करने के लिए; यह भाषा के पुराने संस्करणों के साथ बैकवर्ड-संगतता को संरक्षित करने में भी मदद करता है जहां यादृच्छिक पुनरावृत्ति क्रम अभी भी प्रभाव में है, जैसे कि पायथन 3.5)। (इनाडा नोकी द्वारा योगदान दिया गयाइश्यू 27350 । आइडिया मूल रूप से रेमंड हेटिंगर द्वारा सुझाई गई है ।)

अपडेट दिसंबर 2017: पायथन 3.7 के लिए dictप्रविष्टि प्रविष्टि आदेश की गारंटी है


2
इस धागे को पायथन-देव मेलिंग-लिस्ट पर देखें: mail.python.org/pipermail/python-dev/2016-Seture/146327.html यदि आपने इसे नहीं देखा है; यह मूल रूप से इन विषयों के आसपास एक चर्चा है।
mgc

1
यदि अब काग्रेस को आदेश दिया जाना चाहिए (जो कि अच्छा विचार है) और क्वार्ग्स तानाशाह नहीं हैं, तो मैं अनुमान लगाता हूं कि कोई यह मान सकता है कि दस्तावेज के अन्यथा कहने के बावजूद, पाइकॉन के भविष्य के संस्करण में तानाशाही चाबियाँ आदेशित रहेंगी।
दिमित्री सिन्तसोव

4
@DmitriySintsov नहीं, यह धारणा न बनाएं। यह पीईपी के लेखन के दौरान लाया गया एक मुद्दा था जो ऑर्डर प्रोटेक्टिंग फीचर की परिभाषा को परिभाषित करता है **kwargsऔर जैसे शब्द का इस्तेमाल किया जाता है, वह कूटनीतिक है: **kwargsएक फंक्शन सिग्नेचर में अब इंसर्शन-ऑर्डर-प्रोटेक्टिंग मैपिंग होने की गारंटी है । उन्होंने आदेशात्मक आदेश (और आंतरिक रूप से उपयोग करने के लिए) को लागू करने के लिए किसी भी अन्य कार्यान्वयन के लिए बाध्य नहीं करने के लिए और इस संकेत के लिए कि यह आदेश नहीं है इस तथ्य पर निर्भर नहीं है के रूप में उन्होंने मैपिंग शब्द का उपयोग OrderedDictकिया dictहै।
दिमित्रिस फासारकिस हिलियार्ड

7
रेमंड हेटिंगर की एक अच्छी वीडियो व्याख्या
एलेक्स

1
@wazoox, hashmap का क्रम और जटिलता नहीं बदली है। परिवर्तन कम स्थान को बर्बाद करके हैशमैप को छोटा बनाता है, और बचाया स्थान सहायक सरणी से अधिक (आमतौर पर?) है। तेज़, छोटा, आदेशित - आप सभी को लेने के लिए मिलेंगे 3.
जॉन ला रोय

जवाबों:


510

क्या पायथन में आदेश दिए गए हैं 3.6+?

उन्हें सम्मिलित आदेश दिया गया है [1] । अजगर के 3.6 के रूप में, अजगर के सीपीथॉन कार्यान्वयन के लिए, शब्दकोशों में डाले गए आइटमों के क्रम को याद करते हैंइसे पायथन 3.6 में एक कार्यान्वयन विवरण माना जाता है ; OrderedDictयदि आप सम्मिलन आदेश चाहते हैं, तो आपको इसका उपयोग करने की आवश्यकता है जो कि पायथन के अन्य कार्यान्वयन (और अन्य आदेशित व्यवहार [1] ) के लिए गारंटी है

पायथन 3.7 के रूप में , यह अब एक कार्यान्वयन विवरण नहीं है और इसके बजाय एक भाषा सुविधा बन जाती है। GvR द्वारा एक अजगर-देव संदेश से :

इसे ऐसा बनाओ। "निर्णय प्रविष्टि आदेश रखता है" सत्तारूढ़ है। धन्यवाद!

इसका सीधा सा मतलब है कि आप इस पर निर्भर हो सकते हैं । पायथन के अन्य कार्यान्वयन भी एक आदेश दिया शब्दकोश की पेशकश अगर वे अजगर 3.7 के अनुरूप कार्यान्वयन होना चाहते हैं।


पायथन 3.6डिक्शनरी कार्यान्वयन तत्व आदेश को संरक्षित करते हुए पुराने से बेहतर [2] कैसे करता है ?

अनिवार्य रूप से, दो सरणियों को रखकर

  • पहला सरणी, शब्दकोश में dk_entriesप्रविष्टियाँ दर्ज करने के लिए प्रविष्टियाँ ( प्रकार केPyDictKeyEntry ) रखता है जो उन्हें सम्मिलित किया गया था। परिरक्षण आदेश इसे केवल एक परिशिष्ट के रूप में प्राप्त किया जाता है जहां नई वस्तुओं को हमेशा अंत (प्रविष्टि क्रम) में डाला जाता है।

  • दूसरा, सरणी के dk_indicesलिए सूचकांकों को रखता है dk_entries(अर्थात, मान जो संबंधित प्रविष्टि की स्थिति को इंगित करते हैं dk_entries)। यह सरणी हैश तालिका के रूप में कार्य करती है। जब एक कुंजी को हैश किया जाता है, तो यह एक इंडेक्स में जमा हो जाता है dk_indicesऔर संबंधित प्रविष्टि को अनुक्रमण द्वारा लाया जाता है dk_entries। चूंकि केवल सूचकांक रखे जाते हैं, इस सरणी का प्रकार शब्द के समग्र आकार (प्रकार int8_t( 1बाइट) से लेकर ) int32_t/ int64_t( 4/ 8बाइट्स) 32/ 64बिट बिल्ड पर निर्भर करता है)

पिछले कार्यान्वयन में, प्रकार PyDictKeyEntryऔर आकार का एक विरल सरणी dk_sizeआवंटित किया जाना था; दुर्भाग्य से, इसके परिणामस्वरूप बहुत सारी खाली जगह थी क्योंकि प्रदर्शन कारणों से उस सरणी को 2/3 * dk_sizeपूर्ण से अधिक नहीं होने दिया गया था । (और खाली जगह का आकार अभी भी था !)।PyDictKeyEntry

यह अब ऐसा नहीं है क्योंकि केवल आवश्यक प्रविष्टियों को संग्रहीत किया जाता है (जिन्हें डाला गया है) और प्रकार का एक विरल सरणी intX_t( Xतानाशाह के आकार के आधार पर) 2/3 * dk_sizeपूर्ण रखा गया है। खाली जगह प्रकार से बदल PyDictKeyEntryकरने के लिए intX_t

तो, जाहिर है, प्रकार PyDictKeyEntryका एक विरल सरणी बनाने के भंडारण के लिए विरल सरणी की तुलना में बहुत अधिक स्मृति की मांग है int

यदि आप रुचि रखते हैं, तो इस फीचर के बारे में आप पायथन-देव पर पूरी बातचीत देख सकते हैं , यह एक अच्छा रीड है।


रेमंड हेटिंगर द्वारा किए गए मूल प्रस्ताव में, उपयोग किए गए डेटा संरचनाओं का एक दृश्य देखा जा सकता है जो विचार के सार को पकड़ लेता है।

उदाहरण के लिए, शब्दकोश:

d = {'timmy': 'red', 'barry': 'green', 'guido': 'blue'}

वर्तमान में [कुंजीहश, कुंजी, मान] के रूप में संग्रहीत किया जाता है:

entries = [['--', '--', '--'],
           [-8522787127447073495, 'barry', 'green'],
           ['--', '--', '--'],
           ['--', '--', '--'],
           ['--', '--', '--'],
           [-9092791511155847987, 'timmy', 'red'],
           ['--', '--', '--'],
           [-6480567542315338377, 'guido', 'blue']]

इसके बजाय, डेटा को निम्नानुसार व्यवस्थित किया जाना चाहिए:

indices =  [None, 1, None, None, None, 0, None, 2]
entries =  [[-9092791511155847987, 'timmy', 'red'],
            [-8522787127447073495, 'barry', 'green'],
            [-6480567542315338377, 'guido', 'blue']]

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


[१]: मैं कहता हूं कि "सम्मिलन का आदेश दिया गया" और न कि "आदेश" के बाद से, ऑर्डरडिक्ट के अस्तित्व के साथ, "आदेशित" आगे के व्यवहार का सुझाव देता है जो dictवस्तु प्रदान नहीं करता है । ऑर्डरडाइसीट रिवर्सिबल हैं, ऑर्डर संवेदनशील तरीके प्रदान करते हैं और, मुख्य रूप से, ऑर्डर-सेंसिटिव इक्विलिटी टेस्ट ( ==, !=) प्रदान करते हैं । dictवर्तमान में उन व्यवहारों / विधियों में से कोई भी प्रस्ताव नहीं है।


[२]: नया शब्दकोश कार्यान्वयन अधिक कॉम्पैक्ट रूप से डिज़ाइन किए जाने से बेहतर मेमोरी वार करता है ; यहाँ मुख्य लाभ है। गति के अनुसार, अंतर इतना कठोर नहीं है, ऐसे स्थान हैं जहां नए तानाशाह मामूली प्रतिगमन ( मुख्य-लुकअप, उदाहरण के लिए ) पेश कर सकते हैं , जबकि अन्य में (पुनरावृत्ति और मन में आते हुए) एक प्रदर्शन को बढ़ावा देना चाहिए।

कुल मिलाकर, शब्दकोश की कार्यक्षमता, विशेष रूप से वास्तविक जीवन की स्थितियों में, कॉम्पैक्टनेस की वजह से सुधार होता है।


15
तो, क्या होता है जब एक आइटम को हटा दिया जाता है? है entriesसूची का आकार बदला? या एक रिक्त स्थान रखा जाता है? या यह समय-समय पर संकुचित होता है?
njzk2

18
@ njzk2 जब एक आइटम को हटा दिया जाता है, तो संबंधित इंडेक्स को DKIX_DUMMYमान के साथ बदल दिया जाता है -2और entryसरणी में प्रविष्टि को प्रतिस्थापित किया जाता हैNULL , जब डालने का कार्य किया जाता है तो नए मान एंट्री सरणी में जोड़ दिए जाते हैं, फिर भी विचार करने में सक्षम नहीं है, लेकिन बहुत यकीन है कि जब सूचकांक भरने से परे सूचकांक भर जाता 2/3है तो प्रदर्शन किया जाता है। यदि कई DUMMYप्रविष्टियाँ मौजूद हैं, तो यह बढ़ने के बजाय सिकुड़ सकती है।
दिमित्री फासरकिस हिलियार्ड

3
@ क्रिस_ैंड नोप, एकमात्र वास्तविक प्रतिगमन जो मैंने देखा है, विक्टर के एक संदेश में ट्रैकर पर है । उस माइक्रोबैनमार्क के अलावा, मैंने वास्तविक जीवन के काम के बोझ में गंभीर गति के अंतर को इंगित करने वाला कोई अन्य मुद्दा / संदेश नहीं देखा है। ऐसी जगहें हैं जहां नए तानाशाह मामूली रिग्रेशन (की-लुक्स, उदाहरण के लिए) पेश कर सकते हैं, जबकि अन्य में (पुनरावृत्ति और आकार बदलने का मन में) एक प्रदर्शन को बढ़ावा मिलेगा।
दिमित्री फासरकिस हिलियार्ड 13:14

3
आकार बदलने वाले हिस्से पर सुधार : जब आप आइटम हटाते हैं तो डिस्क्स का आकार परिवर्तन नहीं होता है, जब आप पुन: सम्मिलित करते हैं तो वे पुनः गणना करते हैं। इसलिए, यदि कोई तानाशाही बनाई जाती है d = {i:i for i in range(100)}और आप .popसभी आइटम w / o आवेषण करते हैं, तो आकार नहीं बदलेगा। जब आप इसे फिर से जोड़ते हैं, तो d[1] = 1, उपयुक्त आकार की गणना की जाती है और तानाशाही का आकार बदल जाता है।
४as पर दिमित्री फासरकिस हिलियार

6
@Chris_Rands मुझे पूरा यकीन है कि यह रह रहा है। बात यह है, और यही कारण है कि मैंने ' dictआदेश दिया जा रहा है ' के बारे में कंबल बयानों को हटाने के लिए अपना जवाब बदल dictदिया है, इस अर्थ में आदेश नहीं OrderedDictहैं। उल्लेखनीय मुद्दा समानता है। dictएस के पास असंवेदनशील है ==, OrderedDictएस के पास संवेदनशील आदेश हैं। डंपिंग OrderedDictएस और dictsअब बदलते क्रम में तुलनात्मक तुलना पुराने कोड में बहुत अधिक टूट सकती है। मैं केवल एक चीज का अनुमान लगा रहा हूं जो OrderedDicts के बारे में बदल सकता है वह है इसका कार्यान्वयन।
दिमित्री फासरकिस हिलियार्ड 16

66

नीचे मूल प्रथम प्रश्न का उत्तर दिया जा रहा है:

क्या मुझे पायथन 3.6 में उपयोग करना चाहिए dictया करना चाहिए OrderedDict?

मुझे लगता है कि प्रलेखन से यह वाक्य वास्तव में आपके प्रश्न का उत्तर देने के लिए पर्याप्त है

इस नए कार्यान्वयन के आदेश-संरक्षण पहलू को कार्यान्वयन विवरण माना जाता है और इस पर भरोसा नहीं किया जाना चाहिए

dictस्पष्ट रूप से एक आदेश दिया गया संग्रह नहीं है, इसलिए यदि आप सुसंगत रहना चाहते हैं और नए कार्यान्वयन के साइड इफेक्ट पर भरोसा नहीं करना चाहते हैं OrderedDict

अपना कोड भविष्य प्रमाण बनाएं :)

इस बारे में यहां एक बहस चल रही है

संपादित करें: अजगर 3.7 एक विशेषता के रूप में इस रखेंगे देखें


1
ऐसा लगता है कि यदि उनका मतलब यह नहीं है कि यह एक वास्तविक विशेषता है बल्कि केवल एक कार्यान्वयन विवरण है तो उन्हें इसे दस्तावेज में भी नहीं डालना चाहिए।
21

3
मुझे आपके संपादित चेतावनी के बारे में निश्चित नहीं है; चूंकि गारंटी केवल Python 3.7 के लिए लागू होती है, इसलिए मुझे लगता है कि Python 3.6 के लिए सलाह अपरिवर्तित है, अर्थात CPython में dicts का आदेश दिया गया है, लेकिन इस पर भरोसा मत करो
Chris_Rands

25

अद्यतन: गुइडो वैन रोसुम ने मेलिंग सूची पर घोषणा की कि पायथन के dictसभी कार्यान्वयन में 3.7 s के रूप में सम्मिलन क्रम को संरक्षित करना चाहिए।


2
अब वह मुख्य आदेश आधिकारिक मानक है, ऑर्डरडेड का उद्देश्य क्या है? या, अब यह बेमानी है?
जॉनी वेफल्स

2
मुझे लगता है कि ऑर्डरडिट बेमानी नहीं होगा क्योंकि move_to_endइसकी विधि है और इसकी समानता क्रम संवेदनशील है: docs.python.org/3/library/… । जिम फासाराकिस हिलियार्ड के जवाब पर नोट देखें।
fjsj

@JonnyWaffles जिम के जवाब और इस प्रश्नोत्तर को देखें और एक stackoverflow.com/questions/50872498/…
Chris_Rands

3
अगर आप चाहते हैं कि आपका कोड 2.7 और 3.6 / 3.7 + पर ही चले, तो आपको ऑर्डरडिटक
बोटकोडर


9

मैं ऊपर चर्चा में जोड़ना चाहता था लेकिन टिप्पणी करने के लिए प्रतिष्ठा नहीं है।

पायथन 3.8 अभी तक जारी नहीं किया गया है, लेकिन यह reversed()शब्दकोशों पर फ़ंक्शन को भी शामिल करेगा (एक और अंतर को हटाकर) OrderedDict

डिक्ट और तानाशाही अब उलट () का उपयोग करके उलटा सम्मिलन क्रम में चलने योग्य हैं। (Bpo-33462 में रेमी लापेरे द्वारा योगदान दिया गया।) देखें कि अजगर 3.8 में नया क्या है

मुझे समानता ऑपरेटर या अन्य विशेषताओं का कोई उल्लेख नहीं दिखता है, OrderedDictइसलिए वे अभी भी पूरी तरह से समान नहीं हैं।

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