2009-06-10 14 views
11

मैं How to think like a computer scientist पढ़ रहा हूं जो "पायथन प्रोग्रामिंग" के लिए एक प्रारंभिक पाठ है।मल्टीप्ली ऑपरेटर सूची (डेटा संरचना) पर लागू

सूचियों पर लागू होने पर मैं गुणा करने वाले ऑपरेटर (*) के व्यवहार को स्पष्ट करना चाहता हूं।

पर विचार करें समारोह make_matrix

def make_matrix(rows, columns): 
""" 
    >>> make_matrix(4, 2) 
    [[0, 0], [0, 0], [0, 0], [0, 0]] 
    >>> m = make_matrix(4, 2) 
    >>> m[1][1] = 7 
    >>> m 
    [[0, 0], [0, 7], [0, 0], [0, 0]] 
""" 
return [[0] * columns] * rows 

वास्तविक उत्पादन है

[[0, 7], [0, 7], [0, 7], [0, 7]] 

make_matrix का सही संस्करण है:

def make_matrix(rows, columns): 
""" 
    >>> make_matrix(3, 5) 
    [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]] 
    >>> make_matrix(4, 2) 
    [[0, 0], [0, 0], [0, 0], [0, 0]] 
    >>> m = make_matrix(4, 2) 
    >>> m[1][1] = 7 
    >>> m 
    [[0, 0], [0, 7], [0, 0], [0, 0]] 
""" 
matrix = [] 
for row in range(rows): 
    matrix += [[0] * columns] 
return matrix 

कारण है कि make_matrix के पहले संस्करण में विफल रहता है (के रूप में 9.8 पर किताब में बताया गया है) कि

... प्रत्येक पंक्ति अन्य पंक्तियों के उपनाम है ...

मुझे आश्चर्य है कि क्यों

[[0] * columns] * rows 

का कारण बनता है ... प्रत्येक पंक्ति अन्य पंक्तियों के उपनाम है ...

नहीं बल्कि

+०१२३५१६४१०६१
[[0] * columns] 

अर्थात क्यों एक पंक्ति में प्रत्येक [0] अन्य पंक्ति तत्व के उपनाम नहीं है।

उत्तर

18

पाइथन में सबकुछ ऑब्जेक्ट्स हैं, और पाइथन कभी प्रतिलिपि नहीं बनाते हैं जब तक कि स्पष्टीकरण ने ऐसा करने के लिए कहा न हो।

जब आप

innerList = [0] * 10 

कर आप 10 तत्वों, उन सभी को एक ही int वस्तु 0 की बात कर के साथ एक सूची बना सकते।

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

innerList[1] = 15 

कर आप सूची का दूसरा तत्व बदल रहे हैं इतना है कि यह एक अन्य पूर्णांक 15 को दर्शाता है। यह हमेशा int ऑब्जेक्ट्स अपरिवर्तनीयता के कारण काम करता है।

क्यों

outerList = innerList * 5 

5 तत्वों के साथ एक list वस्तु बनाने विल है कि, हर एक ही innerList बस के रूप में इसके बाद के संस्करण के लिए एक संदर्भ है। लेकिन चूंकि list वस्तुओं परिवर्तनशील हैं:

outerList[2].append('something') 

रूप में एक ही है:

innerList.append('something') 

क्योंकि वे ही list वस्तु करने के लिए दो संदर्भ हैं। तो तत्व उस एकल list में समाप्त होता है। ऐसा लगता है कि डुप्लिकेट किया गया है, लेकिन तथ्य यह है कि केवल एक list ऑब्जेक्ट है, और इसके कई संदर्भ हैं।

इसके विपरीत यदि आप

outerList[1] = outerList[1] + ['something'] 

यहाँ आप पैदा कर रहे करना तक एक औरlist वस्तु (का उपयोग कर + सूचियों के साथ एक स्पष्ट प्रतिलिपि है), और outerList की दूसरी स्थिति में इसे करने के लिए एक संदर्भ बताए । यदि आप इस तरह तत्व को "संलग्न" करते हैं (वास्तव में संलग्न नहीं करते हैं, लेकिन एक और सूची बनाते हैं), innerList अप्रभावित होगा।

+0

सही लगता है, बहुत बहुत धन्यवाद !! – fizzbuzz

+1

+1 - बहुत अच्छी व्याख्या –

-3

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

[[0] * columns] * rows 

ओह, हमने अभी पॉइंटर्स की एक बड़ी सूची बनाई है [0]। एक बदलें और आप उन्हें सभी बदल दें।

इंटीग्रेट संदर्भ द्वारा पारित नहीं किए जाते हैं, इसलिए वास्तव में उनकी प्रतिलिपि बनाई जाती है, इसलिए [0] * सामग्री वास्तव में बहुत से नए 0 बना रही है और उन्हें सूची में जोड़ रही है।

+0

आह, क्या यह आकार 1 की सूची के लिए विशेष प्रकार के व्यवहार की तरह नहीं लगता है। मैंने सुना है कि "पायथनिस्ता" विशेष मामलों को पसंद नहीं करता है (जैसा कि पायथन के जेन में बताया गया है ... विशेष मामले हैं नियम तोड़ने के लिए पर्याप्त विशेष नहीं है .... ")। – fizzbuzz

+4

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

+0

उदाहरण: ए = 5; बी = ए; प्रिंट ए है बी # यह सच है क्योंकि ए और बी एक ही वस्तु के संदर्भ हैं। – nosklo

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