2012-09-07 11 views
12

में एक निर्देश या सूची पर Iterate बस कुछ बुरा कोड लिखा है जो dict या list पर पाइथन में पुनरावृत्त करता है। मुझे एहसास है कि यह इसके बारे में जाने का सबसे अच्छा तरीका नहीं था।पायथन

समस्या

कि आदेश में एक dict से अधिक पुनरावृति करने के लिए, इस सम्मेलन है:

for key in dict_object: 
    dict_object[key] = 1 

लेकिन प्रमुख द्वारा वस्तु के गुण को संशोधित करता है, तो एक ही बात एक सूची पर किया जाता है काम नहीं करता:

# Throws an error because the value of key is the property value, not 
#  the list index: 

for key in list_object: 
    list_object[key] = 1 

तरह से मैं इस समस्या का समाधान इस बुरा कोड लिखा था:

if isinstance(obj, dict): 
    for key in obj: 
     do_loop_contents(obj, key) 
elif isinstance(obj, list): 
    for i in xrange(0, len(obj)): 
     do_loop_contents(obj, i) 

def do_loop_contents(obj, key): 
    obj[key] = 1 

है वहाँ यह करने के लिए एक बेहतर तरीका है?

धन्यवाद!

उत्तर

12

मुझे कभी ऐसा करने की आवश्यकता नहीं है।

seq_iter = x if isinstance(x, dict) else xrange(len(x)) 

उदाहरण के लिए, समारोह के रूप में: लेकिन अगर मैं था, मैं शायद कुछ इस तरह करते हैं होता

>>> def seq_iter(obj): 
...  return obj if isinstance(obj, dict) else xrange(len(obj)) 
... 
>>> x = [1,2,3] 
>>> for i in seq_iter(x): 
...  x[i] = 99 
... 
>>> x 
[99, 99, 99] 
>>> 
>>> x = {1: 2, 2:3, 3:4} 
>>> for i in seq_iter(x): 
...  x[i] = 99 
... 
>>> x 
{1: 99, 2: 99, 3: 99} 
+0

बस देखा गया कि आपके पास मेरा जवाब बहुत समान है। केवल अंतर यह है कि आप 'xrange() '(जो ठीक है) का उपयोग कर रहे हैं, लेकिन नतीजा वही है या बहुत समान है।+1 – Tadeck

+1

यदि लाइन इस्टिंस्टेंस (ओबीजे, dict) अन्य xrange (लेन (ओबीजे)) 'लाइन वापस ओबीजे नहीं होनी चाहिए? –

+0

@tobias_k: अच्छी पकड़! पायथन का स्कोपिंग इन-लाइन संपादन को पूरा करता है। : ^) – DSM

2

pythonic और ducktype-y होने के लिए, और यह भी पालन करने के लिए "के लिए पूछना क्षमा नहीं अनुमति ", आप की तरह कुछ कर सकता है:

:

try: 
    iterator = obj.iteritems() 
except AttributeError: 
    iterator = enumerate(obj) 
for reference, value in iterator: 
    do_loop_contents(obj, reference) 

हालांकि अगर आप सभी की जरूरत कुंजी/सूचकांक है 10

या एक समारोह के रूप:

def reference_and_value_iterator(iterable): 
    try: 
     return iterable.iteritems() 
    except AttributeError: 
     return enumerate(iterable) 

for reference, value in reference_and_value_iterator(obj): 
    do_loop_contents(obj, reference) 

या सिर्फ संदर्भ के लिए:

def references(iterable): 
    try: 
     return iterable.keys() 
    except AttributeError: 
     return range(len(iterable)) 

for reference in references(obj): 
    do_loop_contents(obj, reference) 
5

यह सही तरीका है, लेकिन किसी कारण से आप एक ही तरह से इन दोनों वस्तुओं के इलाज के लिए की जरूरत है

def common_iterable(obj): 
    if isinstance(obj, dict): 
     return obj 
    else: 
     return (index for index, value in enumerate(obj)) 

किस तरह आप चाहते थे में व्यवहार करेंगे:, आप एक iterable कि अनुक्रमित/कुंजी कोई बात नहीं क्या वापस आ जाएगी बना सकते हैं

>>> d = {'a': 10, 'b': 20} 
>>> l = [1,2,3,4] 
>>> for index in common_iterable(d): 
    d[index] = 0 

>>> d 
{'a': 0, 'b': 0} 
>>> for index in common_iterable(l): 
    l[index] = 0 

>>> l 
[0, 0, 0, 0] 

या शायद और अधिक कुशलता से, एक जनरेटर का उपयोग:

def common_iterable(obj): 
    if isinstance(obj, dict): 
     for key in obj: 
      yield key 
    else: 
     for index, value in enumerate(obj): 
      yield index 
+0

यह वास्तव में एक 'इटरेटर' नहीं है, यह सिर्फ एक 'सूची' या 'dict' को एक सतत प्रारूप के पुनरावर्तनीय में बदल देता है। आप एक इटरेटर फैक्ट्री को परिभाषित कर सकते हैं जो इसे 'अगली' और '__iter__' का उपयोग करते हुए पुनरावर्तक प्रोटोकॉल के साथ करता है। –

+0

@ sr2222: ठीक है, यह इष्टतम है। मैं इसे थोड़ा सा प्रदर्शन बढ़ाने के लिए जनरेटर भी बना सकता हूं। – Tadeck

+0

'common_iterable' का आपका दूसरा संस्करण अनावश्यक है। '(सूचकांक के लिए सूचकांक, गणना में मूल्य (ओबीजे)) 'पहले संस्करण से पहले से ही जनरेटर है और' ओबीजे में कुंजी के लिए: उपज कुंजी 'केवल' common_iterable 'के पहले संस्करण में पूरी तरह से ठीक है, –

1
test_list = [2, 3, 4] 
for i, entry in enumerate(test_list): 
    test_list[i] = entry * 2 
print(test_list) # Gives: [4, 6, 8] 

लेकिन आप शायद एक सूची समझ चाहते हैं:

test_list = [2, 3, 4] 
test_list = [entry * 2 for entry in test_list] 
print(test_list) # Gives: [4, 6, 8] 
1

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

if type(object)==type([]): 
    for key in range(len(object)): 
     object[key]=1 
elif type(object)==type({}): #use 'else' if you know that object will be a dict if not a list 
    for key in object: 
     object[key]=1