2012-01-21 14 views
121

पायथन 2.7 में, हमें dictionary view methods उपलब्ध मिला।शब्दकोश देखने के लिए वस्तुएं क्या हैं?

अब, मैं जानता हूँ कि समर्थक और निम्न में से विपक्ष:

  • dict.items() (और values, keys): एक सूची देता है, तो आप वास्तव में परिणाम
  • dict.iteritems() (और) की तरह स्टोर कर सकते हैं : जनरेटर लौटाता है, ताकि आप प्रत्येक मूल्य को एक-एक करके उत्पन्न कर सकें।

dict.viewitems() (और जैसा) क्या हैं? उनके फायदे क्या हैं? यह कैसे काम करता है? सब के बाद क्या विचार है?

मैंने पढ़ा है कि दृश्य हमेशा शब्दकोश के परिवर्तनों को प्रतिबिंबित करता है। लेकिन यह पर्फ और स्मृति बिंदु से कैसे व्यवहार करता है? समर्थक और विपक्ष क्या हैं?

उत्तर

118

शब्दकोश विचार अनिवार्य रूप से उनके नाम क्या कहते हैं: विचार एक शब्दकोश की कुंजी और मान (या आइटम) पर की तरह खिड़की की तरह हैं।

>>> dishes = {'eggs': 2, 'sausage': 1, 'bacon': 1, 'spam': 500} 
>>> keys = dishes.keys() 
>>> values = dishes.values() 

>>> # view objects are dynamic and reflect dict changes 
>>> del dishes['eggs'] 
>>> keys # No eggs anymore! 
dict_keys(['sausage', 'bacon', 'spam']) 

>>> values # No eggs value (2) anymore! 
dict_values([1, 1, 500]) 

(अजगर 2 बराबर dishes.viewkeys() और dishes.viewvalues() उपयोग करता है।)

इस उदाहरण देखा गया की गतिशील चरित्र दिखाता है:: कुंजी देखने नहीं है यहां अजगर 3 के लिए official documentation से एक अंश है समय पर दिए गए बिंदु पर चाबियों की एक प्रति, बल्कि एक साधारण विंडो जो आपको चाबियाँ दिखाती है; अगर वे बदल जाते हैं, तो आप विंडो के माध्यम से जो भी देखते हैं वह भी बदल जाता है। यह सुविधा कुछ परिस्थितियों में उपयोगी हो सकती है (उदाहरण के लिए, किसी भी प्रोग्राम की कई हिस्सों में कुंजियों पर एक दृश्य के साथ काम कर सकते हैं, प्रत्येक बार जब आवश्यक हो तो चाबियों की वर्तमान सूची को पुन: गणना करने के बजाय)।

एक लाभ यह कुंजी स्मृति का केवल एक छोटे और निश्चित राशि का उपयोग करता है और आवश्यकता है प्रोसेसर समय का एक छोटा सा और निश्चित राशि, के रूप में वहाँ की एक सूची का कोई रचना है, कि कहते हैं पर, देख है चाबियाँ (पाइथन 2, दूसरी तरफ, अक्सर अनावश्यक रूप से एक नई सूची बनाती है, जैसा कि राजेंद्रन टी द्वारा उद्धृत किया गया है, जो सूची की लंबाई के अनुपात में स्मृति और समय लेता है)। खिड़की के समानता को जारी रखने के लिए, यदि आप दीवार के पीछे एक परिदृश्य देखना चाहते हैं, तो आप बस इसमें खुलते हैं (आप एक खिड़की बनाते हैं); एक सूची में चाबियों की प्रतिलिपि बनाने के बजाय आपकी दीवार पर परिदृश्य की एक प्रति चित्रित करने के अनुरूप होगा- प्रतिलिपि समय, स्थान लेती है, और खुद को अपडेट नहीं करती है।

सारांशित करने के लिए, आपके शब्दकोश पर विचार ... दृश्य (विंडोज़) हैं, जो इसे बदलने के बाद भी शब्दकोश की सामग्री दिखाते हैं। वे सूचियों से भिन्न सुविधाओं की पेशकश करते हैं: कुंजियों की एक सूची में एक समय पर दिए गए शब्द कुंजी के की प्रतिलिपि होती है, जबकि दृश्य गतिशील होता है और प्राप्त करने के लिए बहुत तेज होता है, क्योंकि इसे किसी भी प्रतिलिपि बनाने की आवश्यकता नहीं होती है बनाए जाने के लिए डेटा (कुंजी या मान)।

+5

+1। ठीक है, यह कुंजी की आंतरिक सूची तक सीधे पहुंचने से अलग कैसे है? क्या वह तेज़, धीमा है? अधिक मेमोरी कुशल? वर्जित ? यदि आप इसे पढ़ और संपादित कर सकते हैं, तो यह बिल्कुल इस सूची का संदर्भ रखने जैसा ही लगता है। –

+2

धन्यवाद। बात यह है कि विचार * आपकी "कुंजी की आंतरिक सूची" तक पहुंच है (ध्यान दें कि यह "कुंजी की सूची" एक पायथन सूची नहीं है, हालांकि, लेकिन यह बिल्कुल एक दृश्य है)। दृश्य पाइथन 2 की कुंजी (या मान या आइटम) की सूचियों की तुलना में अधिक मेमोरी कुशल हैं, क्योंकि वे कुछ भी कॉपी नहीं करते हैं; वे वास्तव में "चाबियों की सूची का संदर्भ" की तरह हैं (ध्यान दें कि "एक सूची का संदर्भ" वास्तव में केवल पाइथन में एक सूची कहा जाता है, क्योंकि सूचियां उत्परिवर्तनीय वस्तुएं होती हैं)। यह भी ध्यान रखें कि आप सीधे दृश्यों को संपादित नहीं कर सकते हैं: इसके बजाय, आप अभी भी शब्दकोश संपादित करते हैं, और विचार तुरंत आपके परिवर्तनों को प्रतिबिंबित करते हैं। – EOL

+2

ठीक है, मैं अभी तक कार्यान्वयन पर स्पष्ट नहीं हूं, लेकिन अब तक का सबसे अच्छा जवाब है। –

13

दृश्य तरीकों एक (सूची की एक प्रति, .keys(), .items() और .values() से तुलना नहीं की) सूची लौटने के लिए, तो यह अधिक हल्के है, लेकिन शब्दकोश की वर्तमान सामग्री को दर्शाता है।

Python 3.0 - dict methods return views - why?

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

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

+2

+1 चल रहा हूँ, लेकिन अभी भी स्पष्ट नहीं क्या एक दृश्य है और यह कैसे काम करता है। –

+4

दृश्य विधियां दृश्य वस्तुएं लौटती हैं, जो सूची इंटरफ़ेस के अनुरूप नहीं होती हैं। हमें मिली कुछ सूचनाओं से समर्थक और विपक्ष का विश्लेषण करने के लिए –

16

बस डॉक्स पढ़ने से मैं इस धारणा मिलती है:

  1. विचार कर रहे हैं "छद्म सेट की तरह", कि वे अनुक्रमण का समर्थन नहीं करते, तो क्या आप उन लोगों के साथ क्या कर सकते हैं परीक्षण है सदस्यता के लिए और उन पर पुनरावृत्त करने के लिए (क्योंकि कुंजी हैंशबल और अद्वितीय हैं, कुंजी और आइटम दृश्य अधिक "सेट-जैसी" हैं जिनमें वे डुप्लीकेट नहीं होते हैं)।
  2. आप उन्हें स्टोर कर सकते हैं और सूची संस्करणों की तरह उन्हें कई बार उपयोग कर सकते हैं।
  3. क्योंकि वे अंतर्निहित शब्दकोश को प्रतिबिंबित करते हैं, शब्दकोश में कोई भी परिवर्तन दृश्य को बदल देगा, और लगभग निश्चित रूप से के क्रम को बदल देगा। तो सूची संस्करणों के विपरीत, वे "स्थिर" नहीं हैं।
  4. क्योंकि वे अंतर्निहित शब्दकोश को प्रतिबिंबित करते हैं, वे लगभग निश्चित रूप से छोटी प्रॉक्सी ऑब्जेक्ट्स हैं; कुंजी/मान/वस्तुओं की प्रतिलिपि बनाने के लिए आवश्यक है कि वे मूल शब्दकोश को किसी भी तरह देखें और परिवर्तन होने पर इसे कई बार कॉपी करें, जो एक बेतुका कार्यान्वयन होगा। तो मैं बहुत कम मेमोरी ओवरहेड की अपेक्षा करता हूं, लेकिन सीधे शब्दकोश से थोड़ा धीमा होने की पहुंच करता हूं।

तो मुझे लगता है कि यदि आप एक शब्दकोश को चारों ओर रखते हैं और बार-बार अपनी चाबियाँ/आइटम/मूल्यों के बीच में संशोधन के साथ पुनरावृत्त करते हैं। आप for k, v in mydict.iteritems(): को for k, v in myview: में बदलकर, इसके बजाय केवल एक दृश्य का उपयोग कर सकते हैं। लेकिन अगर आप एक बार शब्दकोश में फिर से चल रहे हैं, तो मुझे लगता है कि यह संस्करण अभी भी बेहतर है।

+2

+1। –

+0

यदि मैं एक दृश्य पर एक इटरेटर बना देता हूं, तो जब भी शब्दकोश बदलता है तब भी यह अमान्य हो जाता है। यह वही समस्या है जैसा कि शब्दकोश पर एक पुनरावर्तक के साथ (ई। जी। 'Iteritems() ')। तो इन विचारों का क्या मतलब है? मुझे उन्हें कब खुशी होगी? – Alfe

+0

@Alfe आप सही हैं, यह शब्दकोश पुनरावृत्ति के साथ एक समस्या है और विचार इसके साथ मदद नहीं करते हैं। मान लें कि आपको किसी फ़ंक्शन में डिक्शनरी के मानों को पास करने की आवश्यकता है। आप '.values ​​()' का उपयोग कर सकते हैं, लेकिन इसमें एक संपूर्ण प्रतिलिपि को एक सूची के रूप में बनाना शामिल है, जो महंगा हो सकता है। '.itervalues ​​()' है लेकिन आप उनसे अधिक बार उपभोग नहीं कर सकते हैं, इसलिए यह प्रत्येक फ़ंक्शन के साथ काम नहीं करेगा। दृश्यों को एक महंगी प्रति की आवश्यकता नहीं होती है, लेकिन वे अभी भी एक पुनरावर्तक की तुलना में स्टैंड स्टैंड मान के रूप में अधिक उपयोगी हैं। लेकिन वे अभी भी एक ही समय में पुन: प्रयास करने और संशोधित करने में मदद करने के इरादे से नहीं हैं (वहां आप वास्तव में एक प्रतिलिपि चाहते हैं)। – Ben

16

जैसा कि आपने बताया है dict.items() डिक्शनरी की सूची (कुंजी, मूल्य) जोड़े की एक प्रति लौटाता है जो कचरा है और dict.iteritems() शब्दकोश (कुंजी, मान) जोड़े पर एक इटरेटर लौटाता है।

अब निम्नलिखित उदाहरण लेते dict के interator और dict

>>> d = {"x":5, "y":3} 
>>> iter = d.iteritems() 
>>> del d["x"] 
>>> for i in iter: print i 
... 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
RuntimeError: dictionary changed size during iteration 

के एक दृश्य के बीच अंतर को देखने के लिए जबकि एक दृश्य के बस क्या dict में है आपको पता चलता है। यह ध्यान में रखता है कि यह बदल गया है:

>>> d = {"x":5, "y":3} 
>>> v = d.viewitems() 
>>> v 
dict_items([('y', 3), ('x', 5)]) 
>>> del d["x"] 
>>> v 
dict_items([('y', 3)]) 

एक दृश्य बस इतना ही दिखता है कि शब्दकोश अब कैसा दिखता है। प्रविष्टि को हटाने के बाद .items() पुराना हो गया होगा और .iteritems() एक त्रुटि फेंक दी होगी।

+0

महान उदाहरण, धन्यवाद। हालांकि, v = d.items() नहीं होना चाहिए v - d.viewitems() – rix

+0

प्रश्न पायथन 2.7 के बारे में है, इसलिए 'viewitems()' वास्तव में सही है ('आइटम() 'सही ढंग से पाइथन ** में एक दृश्य देता है ** 3 **)। – EOL

+0

हालांकि, एक दृश्य ** ** को संशोधित करते समय एक शब्दकोश में फिर से शुरू करने के लिए उपयोग नहीं किया जा सकता है। –

0

व्यू आपको इसे कॉपी किए बिना अंडरलेइंग डेटा संरचना तक पहुंचने देते हैं। सूची बनाने के विरोध में गतिशील होने के अलावा, उनके सबसे उपयोगी उपयोग में से एक in परीक्षण है। मान लें कि आप यह जांचना चाहते हैं कि कोई मान dict में है या नहीं (या तो यह कुंजी या मान हो)।

विकल्प एक dict.keys() का उपयोग कर चाबियों की एक सूची बनाने के लिए है, यह काम करता है लेकिन स्पष्ट रूप से अधिक स्मृति का उपभोग करता है। यदि निर्देश बहुत बड़ा है? वह अपमानजनक होगा।

views के साथ आप मध्यवर्ती सूची के बिना वास्तविक डेटा-संरचना को पुन: सक्रिय कर सकते हैं।

उदाहरणों का उपयोग करें। मैंने यादृच्छिक तार और अंक और k के 1000 कुंजी के साथ एक dict कुंजी मैं

large_d = { .. 'NBBDC': '0RMLH', 'E01AS': 'UAZIQ', 'G0SSL': '6117Y', 'LYBZ7': 'VC8JQ' .. } 

>>> len(large_d) 
1000 

# this is one option; It creates the keys() list every time, it's here just for the example 
timeit.timeit('k in large_d.keys()', setup='from __main__ import large_d, k', number=1000000) 
13.748743600954867 


# now let's create the list first; only then check for containment 
>>> list_keys = large_d.keys() 
>>> timeit.timeit('k in list_keys', setup='from __main__ import large_d, k, list_keys', number=1000000) 
8.874809793833492 


# this saves us ~5 seconds. Great! 
# let's try the views now 
>>> timeit.timeit('k in large_d.viewkeys()', setup='from __main__ import large_d, k', number=1000000) 
0.08828549011070663 

# How about saving another 8.5 seconds? 

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

नोट: मैं अजगर 2.7 पर

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