डिक्शनरी व्यू ऑब्जेक्ट क्या हैं?


158

अजगर 2.7 में, हमें शब्दकोश देखने के तरीके उपलब्ध हैं।

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

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

के लिए dict.viewitems()(और इस तरह) क्या हैं ? उनके क्या लाभ हैं? यह कैसे काम करता है? आखिर एक नजरिया क्या है?

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

जवाबों:


157

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

>>> 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())

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

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

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


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

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

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

2
धन्यवाद। दरअसल, यह जवाब ज्यादातर विचारों के शब्दार्थ के बारे में है । मुझे सीपीथॉन में उनके कार्यान्वयन के बारे में जानकारी नहीं है, लेकिन मुझे लगता है कि एक दृश्य मूल रूप से सही संरचना (एस) (चाबियाँ और / या मान) के लिए एक संकेतक है, और यह कि संरचना शब्दकोष ऑब्जेक्ट का ही हिस्सा है।
एरिक ओ लेबिगॉट

5
मुझे लगता है कि इस पोस्ट में उदाहरण कोड python3 से इंगित करने योग्य है और मुझे python2.7 में ऐसा नहीं है।
10

21

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

अब एक तानाशाह और तानाशाह के दृष्टिकोण के बीच अंतर को देखने के लिए निम्नलिखित उदाहरण लें

>>> 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

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

>>> 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()होगा और कोई त्रुटि हो गई होगी।


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

1
प्रश्न पायथन 2.7 के बारे में है, इसलिए viewitems()वास्तव में सही है ( items()सही ढंग से पायथन 3 में एक दृश्य देता है )।
एरिक ओ लेबिगॉट

हालाँकि, इसे संशोधित करते हुए किसी शब्द को शब्दकोश में पुनरावृति करने के लिए उपयोग नहीं किया जा सकता है।
आयोनिस फिलिपिपिडिस 20

18

बस डॉक्स पढ़ने से मुझे यह आभास मिलता है:

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

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


2
+1 कुछ प्रो और हमें मिलने वाले विपक्ष से विश्लेषण के लिए।
ई-शनि

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

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

17

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

से अजगर 3.0 - dict तरीकों विचारों वापसी - क्यों?

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

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


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

5

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

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

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

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

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 पर चल रहा हूं


अजगर> = 3 में, मेरा मानना .keys()है कि डिफ़ॉल्ट रूप से एक दृश्य देता है। हो सकता है कि डबल चेक करना चाहते हैं
योलो वो

1
आप सही हे। पायथन 3+ सूची के बजाय दृश्य वस्तुओं का भारी उपयोग करते हैं, यह बहुत अधिक स्मृति कुशल है
चेन ए।

1
ये समय परिणाम बहुत बता रहे हैं, लेकिन जाँच करना कि क्या kशब्दकोश की कुंजी में से एक पायथन के large_dसाथ किया जाना है k in large_d, जो संभवतः एक दृश्य का उपयोग करने के रूप में उतनी ही तेजी से होता है (दूसरे शब्दों में, k in large_d.keys()पायथोनिक नहीं है और इसे टाला जाना चाहिए- जैसा है k in large_d.viewkeys())।
एरिक ओ लेबिगोट

एक ठोस, उपयोगी उदाहरण प्रदान करने के लिए धन्यवाद। k in large_dवास्तव में की तुलना में काफी तेज है k in large_d.viewkeys(), जिससे शायद बचा जाना चाहिए, लेकिन यह समझ में आता है k in large_d.viewvalues()
naught101
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.