2012-01-11 6 views
13
>>> rows = [['']*5]*5 
>>> rows 
[['', '', '', '', ''], ['', '', '', '', ''], ['', '', '', '', ''], ['', '', '', '', ''], ['', '', '', '', '']] 
>>> rows[0][0] = 'x' 

स्वाभाविक रूप से, मैं पंक्तियों बनने के लिए उम्मीद:सूची पर गुणात्मक ऑपरेटर का उपयोग क्यों पॉइंटर्स की सूची बनाते हैं?

[['x', '', '', '', ''], ['', '', '', '', ''], ['', '', '', '', ''], ['', '', '', '', ''], ['', '', '', '', '']] 

इसके बजाय, मैं:

[['x', '', '', '', ''], ['x', '', '', '', ''], ['x', '', '', '', ''], ['x', '', '', '', ''], ['x', '', '', '', '']] 

ऐसा लगता है कि पंक्तियों सूची के तत्वों के संकेत दिए गए हैं वही पुरानी [ ''] * 5 सूची यह इस तरह से क्यों काम करता है और क्या यह एक पायथन सुविधा है?

+0

एक साइड नोट के रूप में, यदि मैं सूची समझ वाक्यविन्यास के माध्यम से सूची बनाता हूं, तो मुझे "ठीक से काम करने वाला" मिलता है: 'पंक्तियां = [['' x में श्रेणी (5) के लिए श्रेणी में (5) ] ' – xyzman

+0

यह भी" काम करता है ": पंक्तियों में वाई के लिए पंक्तियां [[''] * 5 (5)]' – xyzman

उत्तर

15

व्यवहार पुनरावृत्ति ऑपरेटर (*) के लिए विशिष्ट नहीं है। उदाहरण के लिए, यदि आप + का उपयोग कर दो सूचियों को श्रेणीबद्ध, व्यवहार में ही है:

In [1]: a = [[1]] 

In [2]: b = a + a 

In [3]: b 
Out[3]: [[1], [1]] 

In [4]: b[0][0] = 10 

In [5]: b 
Out[5]: [[10], [10]] 

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

निम्नलिखित यह दर्शाता है कि rows के सभी तत्वों को एक ही पहचान (CPython में यानी स्मृति पता है): को छोड़कर यह पंक्तियों के लिए पांच अलग सूचियों बनाता

In [6]: rows = [['']*5]*5 

In [7]: for row in rows: 
    ...:  print id(row) 
    ...:  
    ...:  
15975992 
15975992 
15975992 
15975992 
15975992 

निम्नलिखित अपने उदाहरण के बराबर है:

rows = [['']*5 for i in range(5)] 
3

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

rows = [[''] * 5 for i in range(5)] 

आप अलग अलग अर्थ विज्ञान के साथ एक प्रोग्रामिंग भाषा डिजाइन सकता है, और वहाँ कई भाषाओं करना है कि कर रहे हैं विभिन्न अर्थशास्त्र, साथ ही समान अर्थशास्त्र के साथ भाषाएं। यह निर्णय क्यों दिया गया था जवाब देने में थोड़ा मुश्किल है - एक भाषा में सिर्फ कुछ अर्थशास्त्र होना चाहिए, और आप हमेशा पूछ सकते हैं क्यों। आप यह भी पूछ सकते हैं कि क्यों पाइथन गतिशील रूप से टाइप किया गया है, और अंत में जवाब यह है कि गिडो ने 1 9 8 9 में रास्ता तय किया था।

3

आप सही हैं कि पायथन "हुड के नीचे" पॉइंटर्स का उपयोग कर रहा है, और हां , यह एक विशेषता है। मुझे यकीन नहीं है कि उन्होंने ऐसा क्यों किया - मुझे लगता है कि यह गति के लिए था और स्मृति उपयोग को कम करने के लिए।

यह समस्या, वैसे भी, shallow copies and deep copies के बीच भेद को समझना क्यों महत्वपूर्ण है।

संबंधित मुद्दे