2010-09-01 19 views
38

में शब्दकोश आइटम(), मान(), कुंजी() पर इटरेटिंग यदि मैं सही ढंग से समझता हूं, पाइथन 2, iter(d.keys())d.iterkeys() जैसा ही था। लेकिन अब, d.keys() एक दृश्य है, जो सूची और पुनरावर्तक के बीच में है। दृश्य और पुनरावर्तक के बीच क्या अंतर है?पायथन 3

दूसरे शब्दों में, अजगर 3 में, क्या

for k in d.keys() 
    f(k) 

और

for k in iter(d.keys()) 
    f(k) 

इसके अलावा के बीच का अंतर, कैसे इन मतभेदों को (यदि सभी) एक सरल for पाश में दिखाने करते है?

उत्तर

53

मुझे यकीन नहीं है कि यह आपके प्रश्नों का उत्तर है, लेकिन उम्मीद है कि यह इस संबंध में पायथन 2 और 3 के बीच के अंतर के बारे में कुछ बताता है।

पायथन 2, iter(d.keys()) और d.iterkeys() में काफी समकक्ष नहीं हैं, हालांकि वे वही व्यवहार करेंगे। पहले, keys() कुंजीपटल की कुंजी की एक प्रति वापस लौटाएगा और iter फिर इस सूची में एक इटरेटर ऑब्जेक्ट वापस करेगा, दूसरी की चाबियों की पूरी सूची की एक प्रति कभी नहीं बनाई जाएगी।

दृश्य वस्तुओं अजगर 3 में d.keys() द्वारा दिया iterable (अर्थात पुनरावर्तक उन लोगों से बनाया जा सकता है) तो जब आप कहते हैं for k in d.keys() अजगर आप के लिए इटरेटर पैदा करेगा कर रहे हैं। इसलिए आपके दो उदाहरण समान व्यवहार करेंगे।

keys() के लिए रिटर्न प्रकार के परिवर्तन में महत्व यह है कि पायथन 3 व्यू ऑब्जेक्ट गतिशील है। यानी अगर हम ks = d.keys() कहते हैं और बाद में d में जोड़ें तो ks इसे प्रतिबिंबित करेगा। पायथन 2 में, keys() वर्तमान में dict में सभी कुंजी की एक सूची देता है। की तुलना करें:

अजगर 3

>>> d = { "first" : 1, "second" : 2 } 
>>> ks = d.keys() 
>>> ks 
dict_keys(['second', 'first']) 
>>> d["third"] = 3 
>>> ks 
dict_keys(['second', 'third', 'first']) 

पायथन 2.x

>>> d = { "first" : 1, "second" : 2 } 
>>> ks = d.keys() 
>>> ks 
['second', 'first'] 
>>> d["third"] = 3 
>>> ks 
['second', 'first'] 

अजगर 3 के keys() रिटर्न के रूप में गतिशील वस्तु अजगर 3 नहीं है (और कोई आवश्यकता नहीं है) एक अलग iterkeys विधि।

आगे स्पष्टीकरण

अजगर 3 में, keys() एक dict_keys ऑब्जेक्ट लेकिन अगर हम एक for पाश संदर्भ for k in d.keys() में इसका इस्तेमाल करते हैं तो एक इटरेटर परोक्ष बनाया जाता है। तो for k in d.keys() और for k in iter(d.keys()) के बीच का अंतर इटैरेटर के स्पष्ट बनाम स्पष्ट निर्माण में से एक है।

एक और अंतर के संदर्भ में, जबकि वे गतिशील दोनों हैं, याद रखें कि क्या हम एक स्पष्ट इटरेटर बनाते हैं, तो इसका उपयोग केवल एक बार किया जा सकता है जबकि दृश्य को आवश्यकतानुसार पुन: उपयोग किया जा सकता है। जैसे

>>> ks = d.keys() 
>>> 'first' in ks 
True 
>>> 'second' in ks 
True 
>>> i = iter(d.keys()) 
>>> 'first' in i 
True 
>>> 'second' in i 
False    # because we've already reached the end of the iterator 

इसके अलावा, ध्यान दें कि अगर हम एक स्पष्ट इटरेटर बनाने और उसके बाद dict तो इटरेटर अवैध है संशोधित:

>>> i2 = iter(d.keys()) 
>>> d['fourth'] = 4 
>>> for k in i2: print(k) 
... 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
RuntimeError: dictionary changed size during iteration 

अजगर 2 में, keys की मौजूदा व्यवहार को देखते हुए एक अलग विधि की जरूरत थी पिछली संगतता को बनाए रखने के दौरान कुंजी की सूची कॉपी किए बिना पुनरावृत्त करने का एक तरीका प्रदान करना। इसलिए iterkeys()

+5

2.7 में 'viewkeys() 'है। जो दृश्य देता है। http://docs.python.org/library/stdtypes.html#dict.viewkeys – phadej

+0

धन्यवाद। मैं समझता हूं कि पाइथन 2 की 'd.keys()' अलग है। लेकिन मैं अभी भी पाइथन 3 से 'd.iterkeys()', पायथन 3 से 'd.keys()' और पायथन 3 से 'iter (dkeys()) 'के बीच के अंतर के रूप में उलझन में हूं। जैसा कि मैं समझता हूं, वे सभी गतिशील हैं, और उनमें से कोई भी सूची को आगे नहीं बनाता है? – max

+0

'फॉर' लूप में 'iter (dkeys()) 'और' d.keys()' के बीच कोई अंतर नहीं है, क्योंकि पाइथन आंतरिक रूप से 'iter' को कॉल करता है। इसके अलावा अजगर 2.x 'd.iterkeys()' और py3k 'iter (d.keys()) 'के बीच कोई अंतर नहीं है: दोनों रिटर्न डिक्शनरी-की-इटरेटर। तो सभी तीन वस्तुतः वही हैं। – phadej