2013-07-05 9 views
18

कोई उम्मीद कर रहा है कि कोई मेरी मदद कर सकता है।पायथन: सूची में एक सूची की प्रतिलिपि बनाना

मैं पाइथन के लिए बहुत नया हूं, और मैं यह काम करने की कोशिश कर रहा हूं कि मैं क्या कर रहा हूं।

मैंने पहले ही खोजा है और पाया है कि पाइथन चर को जोड़ा जा सकता है ताकि एक बदलकर दूसरे को बदल दिया जा सके, और मैंने इस अवधारणा के साथ पकड़ने के लिए id() फ़ंक्शन के साथ कई परीक्षण किए हैं। लेकिन मुझे लगता है कि कोई अपवाद मिला है, मुझे उम्मीद है कि कोई समझा सकता है ...

सबसे पहले, निम्न सूची एक सूची की एक स्वतंत्र प्रति बनाने की अपेक्षा की जाती है।

>>> a = [0,0] 
>>> b = a[:] 
>>> print a is b 
False 
>>> b[0]=1 
>>> print a 
[0,0] 
>>> print b 
[1,0] 

लेकिन अगर मैं इस से थोड़ा बदल दें ताकि a एक सूची यह परिवर्तन के भीतर सूची है ...

>>> a = [[0,0],[0,0]] 
>>> b = a[:] 
>>> print a is b 
False 
>>> b[0][0]=1 
>>> print a 
[[1, 0], [0, 0]] 
>>> print b 
[[1, 0], [0, 0]] 

अब हम देखते हैं कि b के किसी भी अद्यतन भी अभी तक a के लिए लागू होगी, लेकिन print a is b का परिणाम False देता है ?? मैंने इसे id() के साथ भी जांच लिया है, सबकुछ कहता है कि वे एक-दूसरे से स्वतंत्र हैं, लेकिन जब मैं एक अपडेट करता हूं तो वही दूसरे पर लागू होता है ??

क्या कोई इसे समझा सकता है ??

नोटिंग मैं http://labs.codecademy.com/#:workspace का इन्हें चला रहा हूं, इसलिए मेरा पहला विचार यह है कि यह उनकी साइट पर बस एक बग है, लेकिन मुझे नहीं पता?

संपादित करें:

अब तक महान जवाब के लिए आप सभी को धन्यवाद। यह तेज़ था! मुझे पता है कि इससे पहले शायद पूछा गया था लेकिन खोजना मुश्किल था।

चूंकि सभी उत्तर सही हैं, इसलिए मैं चिह्नित करने से एक दिन पहले प्रतीक्षा करूंगा। जो कोई भी है सबसे +1, निशान :)

+2

संबंधित: इस तरह http://stackoverflow.com/questions/3119901/python-deepcopylist-vs-new-list-old-list –

उत्तर

18

b = a[:]a के shallow copy बनाता मिल जाएगा तो b भीतर परिवर्तनशील सूचियों को बदलने अभी भी उन्हीं सूचियों a में प्रभाव।

दूसरे शब्दों में, a और b एक ही सूची को इंगित नहीं है, बल्कि करने के लिए दो अलग-अलग सूचियां जो दोनों ही दो सूचियों होते हैं (यही वजह है कि a is not b है)। आप इन सूचियों में से एक को b[0][0] = 1 के माध्यम से बदलते हैं और यह परिवर्तन a में दिखाई देता है।

आपने कहा है कि आप id() के साथ चारों ओर खेल रहे थे, इसलिए इस पर एक नज़र डालें:

>>> a = [[0,0],[0,0]] 
>>> b = a[:] 
>>> id(a) 
2917280     # <----+ 
>>> id(b)     #  |----- different! 
2771584     # <----+ 
>>> id(a[0]), id(a[1]) 
(2917320, 2917360)   # <----+ 
>>> id(b[0]), id(b[1])  #  |----- same! 
(2917320, 2917360)   # <----+ 
13

आप अपनी सूची की एक deepcopy बनाने की जरूरत है। a[:] केवल एक उथले प्रतिलिपि बनाता है - see docs

आप copy.deepcopy फ़ंक्शन का उपयोग कर सकते हैं:

>>> import copy 
>>> a = [[0,0],[0,0]] 
>>> b = copy.deepcopy(a) 
>>> b 
[[0, 0], [0, 0]] 
>>> b[0][0]=1 
>>> a 
[[0, 0], [0, 0]] 
4

a सूचियों की एक सूची है।जब आप b=a[:] करते हैं, तो आप एक नई सूची बनाते हैं, लेकिन तत्वों की प्रतिलिपि बनाते हैं। तो b एक अलग सूची है, लेकिन तत्व (उपन्यास) समान हैं।

3

दोनों मामलों में आप एक स्वतंत्र सूची बनाते हैं। तो a is b हमेशा झूठा है।

पहले मामले में, आप कुछ अन्य मान सूचियों में से एक में डालते हैं।

दूसरे मामले में, आपकी सूचियों में दोनों समान मान होते हैं।

यह है के रूप में यदि आप

l = [] 
a = [l, l] 
b = [l, l] 

a is not b लिखते थे, और फिर भी वे एक ही डेटा है।

आप अब l संशोधित करते हैं, इस परिवर्तन a[0], a[1], b[0] और b[1] के सभी के माध्यम से दिख रहा है।

3

हालांकि a is bFalse, a[0] is b[0] रिटर्न True देता है। तो जब आप b[0] परिवर्तन जरूरी a[0]

>>> a = [[0,0],[0,0]] 
>>> b = a[:] 

>>> # a[0] is b[0] 
>>> print a[0] is b[0] 
True 

>>> a.append('more stuff') 
>>> print a 
[[0, 0], [0, 0], 'more stuff'] 
>>> print b 
[[0, 0], [0, 0]] 
6

बदल रहे हैं मेरा मानना ​​है कि सबसे आसान तरीका क्या हो रहा है प्राप्त करने के लिए एक दृश्य प्रतिनिधित्व उपयोग करने के लिए है (इस प्रतिनिधित्व के विचार है मेरा नहीं है, हालांकि मैं इसे प्यार करता)।

सबसे पहले आपको यह समझना होगा कि पाइथन में केवल संदर्भ ऑब्जेक्ट्स के लिए हैं। ऑब्जेक्ट्स स्वयं अलग से एक दूसरे से रहते हैं। उदाहरण के लिए सूची [0, 1] एक सूची-वस्तु है जिसमें संदर्भ ऑब्जेक्ट 0 और ऑब्जेक्ट 1 पर है। एक संदर्भ किसी प्रकार का लिंक है। यह अन्य भाषाओं में चर से अलग है, क्योंकि वेरिएबल आमतौर पर स्मृति स्थान होते हैं जहां आप चीजें डालते हैं। पायथन में एक "चर", यानी एक पहचानकर्ता, किसी वस्तु के लिए बस "नाम" (= संदर्भ) है।

इसे समझने के लिए, चलो एक रूपक के साथ वस्तुओं के बीच संबंधों को चित्रित करते हैं: मान लें कि वस्तुएं समुद्र में भारी चट्टानें हैं, जो रस्सियों और हुक (¿) द्वारा एक साथ जुड़े हुए हैं। समुद्र की सतह पर पहचानकर्ता जीवित रहते हैं जो वस्तुओं को संदर्भित करता है। पहचानकर्ता बुवाई हैं जो वस्तुओं को गहराई में डूबने से रोकते हैं (जहां, वे कहते हैं, समुद्र राक्षसों (उर्फ कचरा कलेक्टर) उन्हें नष्ट कर देगा)।

a = [0, 1] 
निम्न आरेख के साथ

:

उदाहरण के लिए, हम इस स्थिति का प्रतिनिधित्व कर सकते

  ___ 
     ( ) 
~~~~~~~~(a)~~~~~~~~ 
     (___) 
o  ¿  o 
      |  O 
      | o 
      | 
      | 
    +------+-------+ 
    | [ ¿ , ¿ ] | 
    +----|-----|---+ 
     |  | 
     |  | 
    o |  | 
O  |  | 
     |  | 
     +-+-+ +-+-+ 
     | 0 | | 1 | 
     +---+ +---+ 

o     O o 
    ) 
    ()    o 
))()  ((
(()((  ()) 

आप देख सकते हैं पहचानकर्ता aसंदर्भित करता है, यानी एक रस्सी के साथ जुड़ा हुआ है, सूची वस्तु के लिए। सूची-ऑब्जेक्ट में दो स्लॉट हैं, प्रत्येक में 0 और 1 से जुड़े लिंक शामिल हैं।

अब, अगर हम किया था:

b = a 

पहचानकर्ता bएक ही वस्तु a की को उल्लेख करता है:

  ___     ___ 
      ( )    ( ) 
~~~~~~~~~~~(a)~~~~~~~~~~~~~~~(b)~~~~~~~~~~~~~~~~ 
      (___)    (___) 
      ¿     ¿ 
       \    /
    o   \    /   o 
    o    \   /   o 
       -------+------- 
    O   | [ ¿ , ¿ ] |    O 
       ----|-----|---- 
        |  | 
        +-+-+ +-+-+ 
     o  | 0 | | 1 | 
        +---+ +---+    o 
    O 
     o        O 
             o 


       ) 
      ) (     ) (
     (( )(    (( ) 
     ()) () (   ()) () 

आप, बजाय, के एक उथले प्रतिलिपि करते हैं a, के माध्यम से:

b = a[:] 

एक नई सूची बनाई गई है, और उसके तत्वों प्रतियां संदर्भ वस्तुओं a से जाना जाता के हैं, यानी आप रस्सियों की प्रतियां बनाया है, लेकिन वे एक ही तत्व को इंगित:

   ___     ___ 
       ( )    ( ) 
    ~~~~~~~~~~~(a)~~~~~~~~~~~~~~~(b)~~~~~~~~~~~~~~~~ 
       (___)    (___) 
    O   ¿     ¿    o 
       |     | 
     o   |     | 
       |     | 
      -------+------  ------+------- 
     | [ ¿ , ¿ ] |  | [ ¿ , ¿ ] | 
      ----|----|----  ----|----|---- 
       | |    | | 
       \ \   //
       \ \   //
       \ \  //   o 
    o    \ \  //   o 
        \ \ //    o 
     o   \ \ //
        \ \//   o 
    O     \ X /
         \/\/
         \/ \/ 
         |  | 
         |  | 
         |  | 
         +-+-+ +-+-+ 
         | 0 | | 1 | 
         +---+ +---+ 



       ) 
      ( (    )  (
    )( ) ) )   (( ) ) ) 
    () () ( ( (  ()) () ( ( (

चूंकि पूर्णांक अपरिवर्तनीय हैं, इसलिए प्रतियों या समान समान वस्तुओं का उपयोग करने के बीच कोई अंतर नहीं है, लेकिन जब आप list एस के साथ पूर्णांक को प्रतिस्थापित करते हैं, जो उत्परिवर्तनीय हैं, तो आप उसी ऑब्जेक्ट को संदर्भ संशोधित करते हैं, इसलिए व्यवहार आप देखते हैं।

दिखने में, कोड:

   ___     ___ 
       ( )    ( ) 
    ~~~~~~~~~~~(a)~~~~~~~~~~~~~~~(b)~~~~~~~~~~~~~~~~ 
       (___)    (___) 
    O   ¿     ¿    o 
       |     | 
     o   |     | 
       |     | 
      -------+------  ------+------- 
     | [ ¿ , ¿ ] |  | [ ¿ , ¿ ] | 
      ----|----|----  ----|----|---- 
       |  \   / | 
       |  \   / | 
       |  \  /  | 
       |  \  /  | 
       |   \ /  | 
       |   \ /  | 
       |   \/   | 
       |   X   | 
       |   /\   | 
       |  / \   | 
       |  / \   | 
       |  /  \  | 
       |  /  \  | 
       | /   \  | 
       |  |    \  | 
       |  |    | | 
     +----+-----+----+ +-----+----+----+ 
     | [ ¿ , ¿ ] | | [ ¿ , ¿ ] | 
     +----|-----|----+ +----|-----|----+ 
       \  \   / /
       \  \  / /
       \  \  / /
        \  \ / /
        \  \ / /
        \  |/ /
        | |/ /
        | X /
        | /| /
        |/|/
        \/ \/
         Y  Y 
         |  | 
        +-+-+ +-+-+ 
        | 0 | | 1 | 
        +---+ +---+ 


       ) 
     ( (    )  (
    )( ) ) )   (( ) ) ) 
    () () ( ( (  ()) () ( ( (

नोट कैसे सूची ba का एक ही उप-सूचियों को संदर्भित करता है: में

a = [[0, 1], [0, 1]] 
b = a[:] 

परिणाम। (कार्यान्वयन विस्तार: सीपीथॉन का बाइटकोड संकलक शाब्दिक अभिव्यक्तियों को अनुकूलित करेगा, ताकि एक ही 0 और 1 ऑब्जेक्ट्स दोनों उपन्यासियों में उपयोग किए जाएं। छोटे पूर्णांक के लिए कुछ कैशिंग भी शामिल है, लेकिन यह महत्वपूर्ण नहीं है। सामान्य मामले में उपन्यास सभी तत्वों में आम नहीं है)।

एक गहरी प्रति एक प्रति है जो समान वस्तुओं के इस साझाकरण से बचाती है।

उदाहरण के लिए, को क्रियान्वित करने के बाद:

import copy 
a = [[0, 1], [0, 1]] 
b = copy.deepcopy(a) 

स्थिति है:

   ___            ___ 
       ( )           ( ) 
    ~~~~~~~~~~~(a)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~(b)~~~~~~~~~~~~~~~~ 
       (___)           (___) 
    O   ¿            ¿    o 
       |            | 
     o   |            | 
       |            | 
      -------+------         -------+------ 
     | [ ¿ , ¿ ] |         | [ ¿ , ¿ ] | 
      ----|----|----         ----|----|---- 
       |  \           |  \ 
       |  \           |  \ 
       |  \          |  \ 
       |  \          |  \ 
       |   \          |   \ 
       |   \          |   \ 
       |   \         |   \ 
       |   \         |   \ 
       |    \         |    \ 
       |    \         |    \ 
       |    \        |    \ 
       |    \        |    \ 
     +----+----------+ +--+------------+   +----+----------+ +--+------------+ 
     | [ ¿ , ¿ ] | | [ ¿ , ¿ ] |   | [ ¿ , ¿ ] | | [ ¿ , ¿ ] | 
     +----|-----|----+ +----|-----|----+   +----|-----|----+ +----|-----|----+ 
       \  \   / /      \  \   / /
       \  \  / /      \  \  / /
       \  \  / /       \  \  / /
        \  \ / /       \  \ / /
        \  \ / /        \  \ / /
        \  |/ /        \  |/ /
        | |/ /         | |/ /
        | X /         | X /
        | /| /         | /| /
        |/|/          |/|/
        \/ \/          \/ \/
         Y  Y           Y  Y 
         |  |           |  | 
        +-+-+ +-+-+          +-+-+ +-+-+ 
        | 0 | | 1 |          | 0 | | 1 | 
        +---+ +---+          +---+ +---+ 






       )            ) 
     ( (    )  (    ( (    )  (
    )( ) ) )   (( ) ) )  )( ) ) )   (( ) ) ) 
    () () ( ( (  ()) () ( ( ( () () ( ( (  ()) () ( ( (

(वास्तव में, ऐसा लगता है copy.deepcopy की तरह बहुत चालाक निर्मित वस्तुओं है कि अपरिवर्तनीय हैं नकल से बचने के लिए है, int, long, tuple अपरिवर्तनीय वस्तुओं इत्यादि इसलिए सभी उपन्यास समान 0 और 1 ऑब्जेक्ट्स साझा करते हैं)


ध्यान दें कि ये चित्र आपको यह समझने में भी मदद कर सकते हैं कि संदर्भ गणना कैसे काम करती है। प्रत्येक रस्सी एक संदर्भ है, और जब तक किसी ऑब्जेक्ट में संदर्भों की एक श्रृंखला नहीं होती है जो एक बॉय (यानी एक पहचानकर्ता) तक जाती है, यह जीवित रहता है। जब किसी वस्तु को सतह के बॉयज़ से जोड़ने के लिए कोई और रस्सी नहीं होती है, तो वस्तुएं डूब जाती हैं, और कचरा कलेक्टर द्वारा नष्ट हो जाती हैं।

+4

[यदि आप ASCII कला की तरह] (http: // www .asciiflow.com/# ड्रा) –

0

वहाँ computationally महंगा deepcopy के लिए एक विकल्प है जब आप सूचियों

origvector=[] 
    for ind in range(0, len(testvector)): 
     origvector.append(testvector[ind][:]) 

इस उदाहरण "testvector" में अंदर सूचियों के साथ काम कर रहे हैं n वैक्टर के एक मैट्रिक्स, प्रत्येक आइटम एक तीन आइटम सूची से युक्त है ।

{0,1,2}{10,20,30} 
{3,4,5}{40,50,60} 
{6,7,8}{70,80,90} 
संबंधित मुद्दे