2009-04-07 15 views
110

क्या बीच का अंतर है:पायथन में, ".append()" और "+ = []" के बीच क्या अंतर है?

some_list1 = [] 
some_list1.append("something") 

और

some_list2 = [] 
some_list2 += ["something"] 
+3

संलग्न एक आइटम के लिए है। शायद आप 'विस्तार' का मतलब है। – hasen

+0

'+ =' बनाम 'विस्तार' के अधिक दिलचस्प मामले के लिए: http://stackoverflow.com/questions/3653298/concatenating-two-lists-difference-between-and-extend –

उत्तर

153

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

Python 3.0 (r30:67507, Dec 3 2008, 20:14:27) [MSC v.1500 32 bit (Intel)] on win32 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import timeit 
>>> timeit.Timer('s.append("something")', 's = []').timeit() 
0.20177424499999999 
>>> timeit.Timer('s += ["something"]', 's = []').timeit() 
0.41192320500000079 

Python 2.5.1 (r251:54863, Apr 18 2007, 08:51:08) [MSC v.1310 32 bit (Intel)] on win32 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import timeit 
>>> timeit.Timer('s.append("something")', 's = []').timeit() 
0.23079359499999999 
>>> timeit.Timer('s += ["something"]', 's = []').timeit() 
0.44208112500000141 

सामान्य मामले append में सूची में एक आइटम जोड़ देगा, जबकि += बाएं हाथ की ओर सूची में दाएँ हाथ की ओर सूची के सभी तत्वों कॉपी कर देंगे।

अद्यतन: विश्लेषण

bytecodes तुलना पर्फ़ हम मान सकते हैं कि appendLOAD_ATTR + CALL_FUNCTION में संस्करण कचरे चक्र, और + = संस्करण - BUILD_LIST में। स्पष्ट रूप से BUILD_LISTLOAD_ATTR + CALL_FUNCTION से अधिक है।

>>> import dis 
>>> dis.dis(compile("s = []; s.append('spam')", '', 'exec')) 
    1   0 BUILD_LIST    0 
       3 STORE_NAME    0 (s) 
       6 LOAD_NAME    0 (s) 
       9 LOAD_ATTR    1 (append) 
      12 LOAD_CONST    0 ('spam') 
      15 CALL_FUNCTION   1 
      18 POP_TOP 
      19 LOAD_CONST    1 (None) 
      22 RETURN_VALUE 
>>> dis.dis(compile("s = []; s += ['spam']", '', 'exec')) 
    1   0 BUILD_LIST    0 
       3 STORE_NAME    0 (s) 
       6 LOAD_NAME    0 (s) 
       9 LOAD_CONST    0 ('spam') 
      12 BUILD_LIST    1 
      15 INPLACE_ADD 
      16 STORE_NAME    0 (s) 
      19 LOAD_CONST    1 (None) 
      22 RETURN_VALUE 

हम और भी अधिक LOAD_ATTR भूमि के ऊपर निकाल कर प्रदर्शन में सुधार कर सकते हैं:

>>> timeit.Timer('a("something")', 's = []; a = s.append').timeit() 
0.15924410999923566 
+8

+1: यह बहुत दिलचस्प है। मैं वैसे भी जोड़ना चाहता हूं, क्योंकि इसका परिणाम स्पष्ट कोड में होता है। लेकिन मुझे एहसास नहीं हुआ कि एक प्रदर्शन अंतर था। यदि कुछ भी हो, तो मुझे उम्मीद है कि यह धीमी गति से जुड़ने की उम्मीद है, क्योंकि यह गारंटीकृत फ़ंक्शन कॉल है, जबकि मुझे लगता है कि + = को अनुकूलित किया जाएगा। – DNS

+0

क्या कोई कार्यात्मक अंतर नहीं है? उदाहरण के लिए ** एक = [] **, ** बी = [4,5,6] **, यहां अगर आप ** सी = ए.एपेंड (बी) ** करते हैं तो सी सूची की एक सूची होगी ** [[4,5,6]] ** ** ** सी + = बी **; एक साधारण सूची ** सी = [4,5,6] ** के लिए नेतृत्व करेंगे। – rkioji

+0

बस चीजों को सीधे सेट करने के लिए: + = आपके इनपुट को सही प्रारूप में तब तक विस्तार या संलग्न करने से बेहतर प्रदर्शन देता है। वर्तमान उदाहरण में समय क्या है ['कुछ'] सूची का निर्माण। + = लगभग 15% तेज – Joe

48

उदाहरण आप दे दी है, वहाँ कोई अंतर नहीं, उत्पादन के मामले में, append और += के बीच है। लेकिन append और + (जो मूल रूप से पूछे जाने वाले प्रश्न के बीच) के बीच एक अंतर है।

>>> a = [] 
>>> id(a) 
11814312 
>>> a.append("hello") 
>>> id(a) 
11814312 

>>> b = [] 
>>> id(b) 
11828720 
>>> c = b + ["hello"] 
>>> id(c) 
11833752 
>>> b += ["hello"] 
>>> id(b) 
11828720 

आप देख सकते हैं, append और += ही परिणाम है; वे एक नई सूची के उत्पादन के बिना आइटम को सूची में जोड़ते हैं। + का उपयोग करके दो सूचियां जोड़ती हैं और एक नई सूची तैयार करती हैं।

+0

वहां * संलग्न है * + =। – Constantin

+3

तथ्य यह है कि 'एपेंड' सूची में एक प्रविष्टि जोड़ता है, जबकि + = अन्य सूची में मौजूद हैं (यानी उपनाम 'विस्तार' करने के लिए)। लेकिन वह पहले से ही जानता है कि सवाल किस तरह लिखा गया था। क्या कोई और अंतर है जो मुझे याद आ रहा है? – DNS

+1

एक अंतर है क्योंकि एक संवर्द्धित असाइनमेंट रिबाइंडिंग (मेरे उत्तर में स्पष्टीकरण) प्रस्तुत करता है। – bobince

20
some_list2 += ["something"] 

वहाँ कोई अंतर नहीं है एक मूल्य के लिए वास्तव में

some_list2.extend(["something"]) 

है। प्रलेखन राज्यों, कि:

s.append(x) एक ही रूप में s[len(s):len(s)] = [x]
s.extend(x) एक ही रूप में s[len(s):len(s)] = x

इस प्रकार स्पष्ट रूप से s.append(x) में ही है के रूप में s.extend([x])

39
>>> a=[] 
>>> a.append([1,2]) 
>>> a 
[[1, 2]] 
>>> a=[] 
>>> a+=[1,2] 
>>> a 
[1, 2] 

देखें कि संलग्न करने के लिए एक भी तत्व को जोड़ता है सूची, जो कुछ भी हो सकता है। +=[] सूचियों में शामिल हो जाता है।

+2

इसे वोट देना क्योंकि यह दोनों के बीच एक महत्वपूर्ण अंतर है। अच्छा कार्य। – sli

3

अन्य उत्तर में वर्णित पहलुओं के अलावा, संलग्न करें और + [] क्या आप बहुत अलग व्यवहार है कोशिश कर रहे हैं जब सूचियों की एक सूची बनाने के लिए।

>>> list1=[[1,2],[3,4]] 
>>> list2=[5,6] 
>>> list3=list1+list2 
>>> list3 
[[1, 2], [3, 4], 5, 6] 
>>> list1.append(list2) 
>>> list1 
[[1, 2], [3, 4], [5, 6]] 

List1 + [ '5', '6'] '5' और '6' अलग-अलग तत्वों के रूप में List1 में जोड़ता है। list1.append (['5', '6']) सूची ['5', '6'] सूची 1 में सूची 1 में जोड़ता है।

27

+ = एक असाइनमेंट है। जब आप इसका इस्तेमाल करते हैं तो आप वास्तव में 'some_list2 = some_list2 + [' something ']' कह रहे हैं। कार्य rebinding शामिल है, तो:

l= [] 

def a1(x): 
    l.append(x) # works 

def a2(x): 
    l= l+[x] # assign to l, makes l local 
      # so attempt to read l for addition gives UnboundLocalError 

def a3(x): 
    l+= [x] # fails for the same reason 

+ = ऑपरेटर भी सामान्य रूप से सूची + सूची की तरह एक नई सूची वस्तु बनाना चाहिए सामान्य रूप से कार्य करता है:

>>> l2= l1 
>>> l1+= ['x'] 
>>> l1 is l2 
True 

:

वास्तविकता में
>>> l1= [] 
>>> l2= l1 

>>> l1.append('x') 
>>> l1 is l2 
True 

>>> l1= l1+['x'] 
>>> l1 is l2 
False 

हालांकि ऐसा इसलिए है क्योंकि पाइथन ने +12 संवर्धित असाइनमेंट शॉर्ट-सर्किट और कॉल सूची.extend() को इसके बजाय __iadd__() लागू करने की सूची बनाई है। (यह एक अजीब वार्ट का थोड़ा सा है: यह आम तौर पर आपके द्वारा किया गया काम करता है, लेकिन भ्रमित कारणों के लिए।)

सामान्य रूप से, यदि आप मौजूदा सूची को जोड़/विस्तारित कर रहे हैं, और आप संदर्भ को रखना चाहते हैं एक ही सूची (एक नया बनाने के बजाए), स्पष्ट होना और परिशिष्ट()/विस्तार() विधियों के साथ चिपकना सर्वोत्तम है।

5

यहां प्रदर्शन परीक्षणों सही नहीं हैं:

  1. आप प्रोफ़ाइल केवल एक बार नहीं चलाना चाहिए।
  2. यदि परिशिष्ट बनाम + = [] की तुलना की जाती है तो आपको स्थानीय फ़ंक्शन के रूप में परिशिष्ट घोषित करना चाहिए।

जैसे 64 और 32 बिट:

  • समय परिणाम अलग अजगर संस्करणों पर अलग हैं

    timeit.Timer ('के लिए मैं xrange में (100): एप्लिकेशन (i)', 'एस = []; एप्लिकेशन = s.append') timeit()

    अच्छा परीक्षण यहां पाया जा सकता: http://markandclick.com/1/post/2012/01/python-list-append-vs.html

  • +0

    अभी भी, उस पृष्ठ में + = परीक्षण '+ = [one_var]' का उपयोग करता है। अगर हम सूचियां बनाते हैं, तो + = सबसे तेज़ विकल्प बन जाता है। – Joe

    1

    rebinding व्यवहार अन्य उत्तर में वर्णित कुछ निश्चित परिस्थितियों में फर्क पड़ता है:

    >>> a = ([],[]) 
    >>> a[0].append(1) 
    >>> a 
    ([1], []) 
    >>> a[1] += [1] 
    Traceback (most recent call last): 
        File "<interactive input>", line 1, in <module> 
    TypeError: 'tuple' object does not support item assignment 
    

    ऐसा इसलिए है क्योंकि संवर्धित असाइनमेंट हमेशा पुनर्विचार करता है, भले ही ऑब्जेक्ट को जगह में बदल दिया गया हो। यहां रिबाइंडिंग a[1] = *mutated list* होती है, जो टुपल्स के लिए काम नहीं करती है।

    5

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

    तो:

    myList = [ ] 
    listA = [1,2,3] 
    listB = ["a","b","c"] 
    

    संलग्न का उपयोग करना, आप सूचियों की एक सूची के साथ समाप्त होते हैं:

    >> myList.append(listA) 
    >> myList.append(listB) 
    >> myList 
    [[1,2,3],['a',b','c']] 
    
    ,210

    बजाय CONCATENATE का उपयोग करके आप एक फ्लैट की सूची के साथ अंत:

    >> myList += listA + listB 
    >> myList 
    [1,2,3,"a","b","c"] 
    
    संबंधित मुद्दे