تتكاثر مشغل تطبيق القائمة(هيكل البيانات)
-
13-09-2019 - |
سؤال
أنا أقرأ كيف يفكر مثل عالم الكمبيوتر وهو نص تمهيدي عن "البرمجة بايثون".
أريد أن أوضح سلوك ضرب المشغل (*
) عندما يطبق على القوائم.
النظر في وظيفة 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]
في صف واحد هو مستعار من صف آخر عنصر.
المحلول
كل شيء في بيثون هي كائنات، والبيثون لا يجعل النسخ أبدا ما لم يطلب من السطورة القيام بذلك.
عندما تفعل
innerList = [0] * 10
يمكنك إنشاء قائمة مع 10 عناصر، كلهم يشيرون إلى نفسه int
هدف 0
.
منذ كائنات عدد صحيح ثابت, ، عندما تفعل
innerList[1] = 15
أنت تغير العنصر الثاني من القائمة بحيث يشير إلى عدد صحيح آخر 15
. وبعد هذا يعمل دائما بسبب int
الكائنات الدخانية.
لهذا
outerList = innerList * 5
سوف تنشئ أ list
كائن مع 5 عناصر، كل واحد هو إشارة إلى نفس الشيء innerList
على النحو الوارد أعلاه. لكن منذ list
الكائنات متقلب:
outerList[2].append('something')
بالضبط مثل:
innerList.append('something')
لأنهم مراجعان إلى نفس list
هدف. وبعد لذلك ينتهي العنصر في هذا واحد list
. وبعد يبدو أنه مكررة، لكن الحقيقة هي أن هناك واحدة فقط list
الكائن، والعديد من المراجع إليها.
على النقيض من ذلك إذا قمت بذلك
outerList[1] = outerList[1] + ['something']
ها انت خلق اخر list
هدف (استخدام +
مع القوائم هي نسخة واضحة)، وتعيين مرجع إليها في المرتبة الثانية من outerList
. وبعد إذا كنت "إلحاق" العنصر بهذه الطريقة (لا تملك حقا، ولكن إنشاء قائمة أخرى)، innerList
سوف لا تتأثر.
نصائح أخرى
القوائم ليست الأوليات ، تمريرها من قبل المرجعية.نسخة من قائمة مؤشر إلى قائمة (في ج المصطلحات).أي شيء يمكنك القيام به قائمة يحدث لجميع نسخ من القائمة نسخ محتوياته إلا إذا كنت تفعل نسخة الضحلة.
[[0] * columns] * rows
عفوا لقد قدمت قائمة كبيرة من المؤشرات [0].تغيير واحد و تغيير كل منهم.
الاعداد الصحيحه لا يتم تمرير من قبل المرجعية ، هم حقا نسخ, ولذلك [0] * المحتويات هو حقا جعل الكثير من 0 و إلحاق لهم قائمة.