الفرق بين == و is في بايثون: متى تستخدم كل واحد؟ | أساسيات بايثون 41

الفرق بين == و is في بايثون ومتى تستخدم كل واحد

== تقارن القيم، أما is فتتحقق هل المتغيران يشيران إلى الكائن نفسه.

a = [1, 2, 3]
b = [1, 2, 3]

print(a == b)
print(a is b)

الناتج:

True
False

القائمتان تحتويان القيم نفسها، لذلك a == b ترجع True. لكن كل قائمة كائن مستقل، لذلك a is b ترجع False.

هذه هي الفكرة الأساسية:

  • Value Equality: استخدم == عندما يهمك تساوي القيمة أو المحتوى.
  • Object Identity: استخدم is عندما يهمك أن يكون الطرفان هما الكائن نفسه.

هذا هو الدرس 41 من سلسلة أساسيات بايثون.

إذا أردت مراجعة معاملات المقارنة والهوية بصورة عامة، راجع أساسيات بايثون 6: شرح Operators في بايثون. أما هذا الدرس فيركز على الفرق بين == وis.

{getToc} $title={محتوى المقال}

الفرق بين == و is بسرعة

المعاملماذا يقارن؟الاستخدام المعتادمثال
==القيمة أو المحتوى حسب نوع الكائن.الأرقام، النصوص، القوائم، والقيم عندما نهتم بالمحتوى.x == 5
isهوية الكائن.غالبًا مع None أو عندما نريد التأكد أنه الكائن نفسه.value is None
{alertInfo} القاعدة العملية: إذا كان السؤال «هل القيمتان متساويتان؟» استخدم ==. وإذا كان السؤال «هل هذا هو الكائن نفسه؟» استخدم is.

مثال يوضح أن == تقارن القيمة وis تقارن هوية الكائن في بايثون

قائمتان متساويتان في المحتوى لكنهما كائنان مختلفان

a = [10, 20]
b = [10, 20]

print(a == b)
print(a is b)

الناتج:

True
False

== ترى أن محتوى القائمتين متساوٍ، بينما is ترى أنهما كائنان مستقلان.

للتوسع في القوائم راجع أساسيات بايثون 16: شرح Lists في بايثون.

عندما يشير متغيران إلى القائمة نفسها

a = [10, 20]
b = a

print(a == b)
print(a is b)

الناتج:

True
True

السطر b = a لا ينشئ قائمة جديدة؛ بل يجعل b يشير إلى الكائن نفسه.

تعديل alias يوضح معنى «نفس الكائن»

a = [10, 20]
b = a

b.append(30)

print(a)
print(b)

الناتج:

[10, 20, 30]
[10, 20, 30]

ظهر التعديل في a وb لأنهما يشيران إلى القائمة نفسها.

نسخة مستقلة باستخدام copy()

a = [10, 20]
b = a.copy()

print(a == b)
print(a is b)

b.append(30)

print(a)
print(b)

الناتج:

True
False
[10, 20]
[10, 20, 30]

في البداية كانت القيم متساوية، لذلك a == b كانت True. لكن النسخة كائن مستقل، لذلك a is b كانت False. وبعد تعديل b لم تتغير a.

أهم استخدام عملي لـ is: مع None

value = None

if value is None:
    print("لا توجد قيمة")

وعندما تريد التأكد أن القيمة ليست None:

result = "done"

if result is not None:
    print(result)

هذا هو الأسلوب الموصى به في بايثون: استخدم is None وis not None عند المقارنة مع None.

استخدام is None وis not None في بايثون

لماذا لا نكتب == None عادةً؟

قد يعمل value == None في حالات بسيطة، لكنه ليس الأسلوب الموصى به. None Singleton، والمقصود هنا هو التحقق من هوية الكائن نفسه.

اكتب:

value = None

if value is None:
    print("لا توجد قيمة")

وللعكس استخدم is not None.

is not ليست بديلًا عن !=

name = "Omar"

if name != "Ali":
    print("Different value")

!= تقارن عدم تساوي القيم. أما is not فتختبر أن الطرفين ليسا الكائن نفسه.

خطأ شائع: استخدام is مع الأرقام

لا تستخدم هذا لمقارنة القيمة:

x = 100

if x is 100:
    print("Equal")

الصحيح:

x = 100

if x == 100:
    print("Equal")

إذا كنت تقارن قيمة رقمية، استخدم ==. لا تعتمد على نتيجة is حتى لو بدت صحيحة في تجربة معينة.

لماذا تبدو is وكأنها تعمل أحيانًا مع الأرقام؟

قد تعيد بعض تطبيقات بايثون استخدام كائنات أو ثوابت معينة كتحسين داخلي. لذلك قد ترى نتائج مربكة في بيئة أو سياق معيّن.

لا تحفظ قاعدة من نوع «is تعمل مع أرقام معينة». هذه تفاصيل تنفيذية قد تختلف حسب الإصدار والمفسر وكيفية إنشاء القيمة.

{alertWarning} القاعدة الصحيحة: قيمة رقمية → ==. هوية الكائن → is.

Python الحديثة قد تحذرك عند is مع Literal

في Python الحديثة قد يؤدي استخدام is مباشرة مع Literal رقمي إلى SyntaxWarning مثل:

"is" with 'int' literal. Did you mean "=="?

التحذير نفسه يذكرك بأن مقارنة القيمة الرقمية تكون باستخدام ==.

لا تستخدم is لمقارنة Strings

لمقارنة محتوى النص:

name = "Ali"

if name == "Ali":
    print("Matched")

بعض Strings قد يعاد استخدامها داخليًا، لذلك لا تعتمد على is حتى لو أعطت نتيجة متوقعة مرة.

لماذا لا نعتمد على is لمقارنة النصوص؟

name1 = "Python"
name2 = "".join(["Py", "thon"])

print(name1 == name2)
print(name1 is name2)

الناتج في البيئة المستخدمة لهذا المثال:

True
False

name1 == name2 تقارن محتوى النصين، وهذه هي المقارنة الصحيحة عندما نريد معرفة هل النصان متساويان في القيمة.

أما نتيجة name1 is name2 فتتعلق بهوية الكائنين، وقد تتأثر بطريقة إنشاء النص وتفاصيل التنفيذ والسياق. لذلك لا نستخدم is لاختبار مساواة Strings حتى لو أعطت النتيجة المتوقعة في تجربة معينة.

== مع Dictionaries

user1 = {
    "name": "Ali",
    "age": 20
}

user2 = {
    "name": "Ali",
    "age": 20
}

print(user1 == user2)
print(user1 is user2)

الناتج:

True
False

القاموسان يحتويان البيانات نفسها، لذلك == ترجع True. لكنهما قاموسان مستقلان، لذلك is ترجع False.

للتوسع راجع أساسيات بايثون 18: شرح Dictionaries في بايثون.

ماذا يفعل == تقنيًا؟

الأنواع والكلاسات يمكن أن تحدد معنى المساواة بينها، وغالبًا يرتبط ذلك بالطريقة الخاصة __eq__(). لا تحتاج إلى Magic Methods الآن؛ المهم أن == تسأل عن معنى المساواة لذلك النوع.

أما is وis not فمعناهما ثابت: اختبار هوية الكائن، ولا يمكن تخصيص هذا المعنى.

ما فائدة id() هنا؟

a = [1, 2]
b = a
c = [1, 2]

print(id(a))
print(id(b))
print(id(c))

سترى أن a وb لهما نفس قيمة id() أثناء عمر الكائن، بينما c لها قيمة أخرى. الأرقام نفسها تختلف بين التشغيلات.

id() تعيد هوية فريدة للكائن أثناء حياته. لا تعرّفها للمبتدئ ببساطة على أنها «عنوان الذاكرة»؛ بعض التطبيقات قد تمثلها بطريقة مرتبطة بالذاكرة، لكن هذا ليس الضمان العام للغة.

{alertInfo} استخدم a is b إذا أردت فحص الهوية. استخدم id() هنا للفهم والتجربة، لا كبديل عادي لـis.

Mutable وImmutable لا تغير قاعدة المقارنة

القوائم والقواميس وSets قابلة للتعديل، بينما الأرقام والنصوص وTuples أمثلة شائعة على أنواع Immutable. لكن لا تستنتج من ذلك أن is تصلح لمقارنة قيم الأنواع Immutable.

حتى مع int وstr: مقارنة القيمة تكون باستخدام ==.

ماذا عن True وFalse؟

في معظم الشروط، إذا كان لديك Boolean حقيقي، اكتب ببساطة:

flag = True

if flag:
    print("Enabled")

ولا تجعل if flag == True أو if flag is True أسلوبك الافتراضي بلا حاجة.

Truthy ليست نفسها is True

value = 1

print(bool(value))
print(value is True)

الناتج:

True
False

القيمة 1 Truthy، لذلك bool(value) أعطت True، لكنها ليست الكائن True نفسه في اختبار الهوية.

لفهم True وFalse وTruthy وFalsy راجع أساسيات بايثون 20: شرح Boolean.

جدول اختيار عملي

أريد أن أعرف...أستخدم
هل x قيمتها 10؟x == 10
هل name تساوي "Ali"؟name == "Ali"
هل القائمتان تحتويان العناصر نفسها؟list1 == list2
هل المتغيران يشيران إلى القائمة نفسها؟list1 is list2
هل value هي None؟value is None
هل value ليست None؟value is not None
هل قيمتان مختلفتان؟a != b

مثال تشخيصي: توقع النتائج قبل التشغيل

a = [1, 2, 3]
b = [1, 2, 3]
c = a

print(a == b)
print(a is b)
print(a == c)
print(a is c)

الناتج:

True
False
True
True

لأن a وb قائمتان مستقلتان بمحتوى متساوٍ، بينما c = a تجعل c تشير إلى القائمة نفسها.

يمكنك تجربة المثال وتغيير القيم في محرر بايثون العرب.

أخطاء شائعة

  • استخدام is بدل == مع الأرقام.
  • استخدام is بدل == مع Strings.
  • الاعتقاد أن == تعني نفس الكائن.
  • الاعتقاد أن is تقارن المحتوى.
  • استخدام == None بدل is None في الكود الموصى به.
  • الاعتماد على نتيجة is مع Integer أو String لأنها أعطت True مرة.
  • استخدام id() بدل is.
  • استخدام is not بدل != لمقارنة القيم.

تذكير سريع: = و == و is

الرمزالمعنى
=إسناد قيمة إلى متغير.
==مقارنة القيم.
isمقارنة هوية الكائن.

وتظهر المقارنات كثيرًا داخل الشروط؛ راجع أساسيات بايثون 11: شرح if وelse.

تمرين بسيط

توقع النتائج قبل التشغيل:

x = {"name": "Ali"}
y = {"name": "Ali"}
z = x

print(x == y)
print(x is y)
print(x == z)
print(x is z)

الحل:

True
False
True
True

x وy قاموسان مستقلان لكن محتواهما متساوٍ. أما z = x فتعني أن z تشير إلى القاموس نفسه.

مصادر رسمية

الخلاصة

  • مقارنة قيمة → ==.
  • مقارنة هوية → is.
  • التحقق من Noneis None.
  • التحقق من عدم Noneis not None.
  • الأرقام والنصوص من حيث القيمة → ==.
{alertSuccess} القاعدة الذهبية: قيمة → ==، هوية → is، وNone → is None.

أسئلة شائعة

ما الفرق بين == و is في بايثون؟

== تقارن القيم أو المحتوى وفق معنى المساواة لذلك النوع، بينما is تتحقق هل الطرفان هما الكائن نفسه.

متى أستخدم ==؟

استخدمها عند مقارنة الأرقام والنصوص أو محتوى Lists وDictionaries وغيرها.

متى أستخدم is؟

استخدمها لاختبار الهوية، وأشهر استخدام للمبتدئ هو is None وis not None.

لماذا نستخدم is None؟

لأن None Singleton، وإرشادات بايثون توصي بمقارنته باستخدام is أو is not.

هل يمكن استخدام is مع الأرقام؟

لا تستخدمها لمقارنة القيمة الرقمية. استخدم ==. وقد تعرض Python الحديثة SyntaxWarning عند استخدام is مع Literal.

هل يمكن استخدام is مع Strings؟

لا تستخدمها لمقارنة محتوى النصوص. قد تظهر نتيجة مربكة بسبب إعادة استخدام بعض الكائنات داخليًا، لذلك استخدم ==.

لماذا تعطي قائمتان True مع == وFalse مع is؟

لأن القائمتين قد تحتويان العناصر نفسها، لكن كل واحدة منهما كائن مستقل.

ما معنى Object Identity في بايثون؟

تعني هوية الكائن نفسه أثناء حياته. إذا كانت a is b تساوي True فهذا يعني أن الاسمين يشيران إلى الكائن نفسه.

ما الفرق بين is not و !=؟

is not تختبر أن الطرفين ليسا الكائن نفسه، بينما != تختبر أن القيمتين غير متساويتين.

إرسال تعليق

أحدث أقدم