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


121

दोनों के बीच क्या अंतर है:

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

तथा

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

3
अगर एक आइटम के लिए अपील। शायद आपका मतलब है extend
hasen

+=बनाम के अधिक दिलचस्प मामले के लिए extend: stackoverflow.com/questions/3653298/…
Ciro Santilli 病 of of of '17

जवाबों:


160

आपके मामले के लिए एकमात्र अंतर प्रदर्शन है: परिशिष्ट दो बार तेज है।

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में सूची में एक आइटम जोड़ा जाएगा, जबकि दाएं हाथ-साइड सूची के सभी तत्वों को बाईं ओर की सूची में +=कॉपी किया जाएगा ।

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

बाइटकोड की तुलना में हम यह मान सकते हैं कि appendसंस्करण में LOAD_ATTR+ CALL_FUNCTION, और + = संस्करण में चक्र बर्बाद होता है BUILD_LIST। जाहिरा तौर पर BUILD_LISToutweighs LOAD_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

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

2
वहाँ भी एक कार्यात्मक अंतर नहीं है? उदाहरण के लिए a = [] , b = [4,5,6] , अगर आप c = a.append (b) करते हैं तो c सूची [[4,5,6]] जबकि c + होगा = बी ; एक साधारण सूची c = [4,5,6] तक ले जाएगा
12

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

@ जो यदि आप appendबनाम तुलना कर रहे हैं +=, तो आपको माप के भाग के रूप में सूची का निर्माण शामिल करना होगा । अन्यथा यह एक अलग प्रश्न होगा ( extendबनाम +=)।
jamesdlin

@jamesdlin युप! लेकिन यह गलत है जब तक आप पहले से ही यह नहीं जानते। थोड़ी अतिरिक्त सटीकता ने कभी किसी को चोट नहीं पहुंचाई है, है ना?
जो

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और +=एक ही परिणाम है; वे नई सूची तैयार किए बिना आइटम को सूची में जोड़ते हैं। का उपयोग +कर दो सूचियों को जोड़ता है और एक नई सूची तैयार करता है।


वहाँ है संलग्न और + = के बीच का अंतर।
कांस्टेंटिन

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

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

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

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


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

31

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

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

+ = ऑपरेटर को आम तौर पर एक नई सूची ऑब्जेक्ट बनाना चाहिए जैसे सूची + सूची सामान्य रूप से होती है:

>>> l1= []
>>> l2= l1

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

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

हालांकि वास्तविकता में:

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

इसका कारण यह है कि पायथन सूचियाँ __idd __ () को लागू करने के बजाय एक + = संवर्धित असाइनमेंट शॉर्ट-सर्किट और कॉल लिस्ट बनाती हैं। कस्टम () के बजाय। (यह एक अजीब मस्सा का एक सा है: यह आमतौर पर वही करता है जो आपका मतलब था, लेकिन भ्रमित करने वाले कारणों के लिए।)

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


21
 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])


s.append एक मनमाना प्रकार लेता है और इसे सूची में जोड़ता है; यह एक सही परिशिष्ट है। s.extend एक iterable (आमतौर पर एक सूची) लेता है, और s के मेमोरी पतों को संशोधित करते हुए, iterable को s में जोड़ता है। ये समान नहीं हैं ।
W4t3randWind

9

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

तो उदाहरण के लिए:

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

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

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

इसके बजाय समवर्ती का उपयोग करते हुए, आप एक फ्लैट सूची के साथ समाप्त होते हैं:

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

5

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

  1. आपको केवल एक बार प्रोफ़ाइल नहीं चलाना चाहिए।
  2. यदि एपेंड की तुलना बनाम + = [] कई बार आपको एक स्थानीय फ़ंक्शन के रूप में एपेंड की घोषणा करनी चाहिए।
  3. समय के परिणाम विभिन्न अजगर संस्करणों पर भिन्न होते हैं: 64 और 32 बिट

जैसे

timeit.Timer ('i for xrange (100): ऐप (i)', 's = []; ऐप = s.append')। timeit ()।

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


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

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'] व्यक्तिगत तत्वों के रूप में list1 में '5' और '6' जोड़ता है। list1.append (['5', '6']) एक तत्व के रूप में list1 में सूची ['5', '6'] जोड़ता है।


2

अन्य उत्तरों में वर्णित विद्रोही व्यवहार कुछ परिस्थितियों में मायने रखता है:

>>> 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*, जो ट्यूपल्स के लिए काम नहीं करता है।


0

पहले एक उदाहरण लेते हैं

list1=[1,2,3,4]
list2=list1     (that means they points to same object)

if we do 
list1=list1+[5]    it will create a new object of list
print(list1)       output [1,2,3,4,5] 
print(list2)       output [1,2,3,4]

but if we append  then 
list1.append(5)     no new object of list created
print(list1)       output [1,2,3,4,5] 
print(list2)       output [1,2,3,4,5]

extend(list) also do the same work as append it just append a list instead of a 
single variable 

0

परिशिष्ट () विधि मौजूदा सूची में एक एकल आइटम जोड़ता है

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

तो यहाँ some_list1 संशोधित हो जाएगा।

अपडेट किया गया:

जबकि विस्तार के समान मौजूदा सूची में सूचियों के तत्वों (एक से अधिक तत्वों) को संयोजित करने के लिए + का उपयोग करना (जैसा कि फ्लक्स द्वारा सही किया गया है )।

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

तो यहाँ some_list2 और ["कुछ"] दो सूचियाँ हैं जो संयुक्त हैं।


1
ये गलत है। +=नई सूची नहीं लौटाता है। प्रोग्रामिंग पूछे जाने वाले प्रश्न कहते हैं: "... सूचियों के लिए, __iadd__बुला के बराबर है extendइस सूची में और सूची लौटने के हम क्यों कहते है कि सूचियों के लिए,। +=एक है" "के लिए आशुलिपि list.extend"। आप CPython स्रोत कोड में अपने लिए भी इसे देख सकते हैं: github.com/python/cpython/blob/v3.8.2/Objects/…
Flux

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.