cb
codebamin
الفصل 6 · القوائم (Lists)

الفرق بين تطابق القيمة (==) وتطابق الكائن (is)

حان الوقت لتعلم بعض التفاصيل التقنية التي يساء فهمها كثيرًا وقد تسبب أخطاء. شغّل هذا البرنامج:

__copyable__ __program_indented__

هذا البرنامج مباشر إلى حد كبير ويتكون أساسًا من أفكار تعرفها بالفعل. ننشئ متغيرين يشيران إلى قائمتين. وبما أن القائمتين تحتويان على العناصر نفسها، فهما متساويتان من حيث القيمة: التعبير list1 == list2 يساوي True.

لكن يظهر هنا معامل مقارنة جديد هو is. في هذا المثال تكون نتيجة list1 is list2 هي False. هذا يعني أنه رغم تساوي القائمتين في المحتوى، فإنهما ما زالتا قائمتين منفصلتين ومختلفتين ككائنين في الذاكرة. ولهذا، عندما تضيف 4 إلى list1 باستخدام append تتغير list1 وحدها.

غيّر الآن list2 = [1, 2, 3] إلى list2 = list1، ثم راقب الفرق.

الآن أصبحت نتيجة list1 is list2 هي True، لأن هناك قائمة واحدة فقط والمتغيرين list1 وlist2 يشيران إلى الكائن نفسه. لذلك فإن list1.append(4) تضيف إلى تلك القائمة الواحدة، ويظهر التغيير عند طباعة list1 وعند طباعة list2 لأن الاسمين أصبحا طريقتين للوصول إلى القائمة نفسها.

من المفيد تشغيل النسختين داخل متتبع لحالة البرنامج لترى الفرق بصريًا. في الحالة الثانية سترى المتغيرين يشيران إلى كائن قائمة واحد.

السطر list2 = list1 لا يصنع رابطًا دائمًا بين المتغيرين. إذا أسندت قيمة جديدة إلى أحدهما لاحقًا، مثل list1 = [7, 8, 9]، فلن يتأثر المتغير الآخر وسيظل يشير إلى القائمة القديمة.

بصورة عامة، الإسناد:

list2 = <expression>

يعني: «اجعل المتغير list2 يشير إلى القيمة التي ينتجها <expression>». لا تُنشأ نسخة من القيمة تلقائيًا، ولذلك قد يشير متغيران إلى كائن القائمة نفسه. وفي الوقت نفسه، list2 لا يتذكر التعبير الذي أنتج القيمة ولا يعرف شيئًا عن المتغيرات الأخرى؛ إنه يحتفظ فقط بالإشارة إلى القيمة الحالية.

إذا أردت نسخة مستقلة من قائمة يمكنك استخدام الأسلوب copy:

list2 = list1.copy()

وبذلك يعود البرنامج إلى السلوك الذي رأيته عندما كانت القائمتان منفصلتين.

إذا صادفت مشكلة من هذا النوع لاحقًا، فركّز على السؤال التالي: هل لدي كائنان منفصلان لهما القيم نفسها، أم اسمان يشيران إلى الكائن نفسه؟ هذه الفكرة هي المفتاح لفهم سلوك القوائم والكائنات القابلة للتعديل.

solution.py
1
2
3
4
5
6
7
8
9
10
الطرفية (shell)
>>>