هل هناك فرق بين "foo is لا شيء" و"foo == لا شيء"؟
-
09-06-2019 - |
سؤال
هل هناك فرق بين:
if foo is None: pass
و
if foo == None: pass
التقليد الذي رأيته في معظم أكواد بايثون (والكود الذي أكتبه بنفسي) هو الأول، لكنني عثرت مؤخرًا على كود يستخدم الأخير.لا شيء هو مثيل (والمثيل الوحيد، IIRC) لـ NonType، لذا لا ينبغي أن يكون الأمر مهمًا، أليس كذلك؟هل هناك أي ظروف قد يكون فيها ذلك؟
المحلول
is
يعود دائما True
إذا كان يقارن نفس مثيل الكائن
بينما ==
يتم تحديده في النهاية بواسطة __eq__()
طريقة
أي.
>>> class Foo(object):
def __eq__(self, other):
return True
>>> f = Foo()
>>> f == None
True
>>> f is None
False
نصائح أخرى
قد ترغب في قراءة هذا هوية الكائن والتكافؤ.
يتم استخدام العبارة 'is' لهوية الكائن، فهي تتحقق مما إذا كانت الكائنات تشير إلى نفس المثيل (نفس العنوان في الذاكرة).
وتشير العبارة '==' إلى المساواة (نفس القيمة).
كلمة تحذير:
if foo:
# do something
يكون لا بالضبط مثل:
if x is not None:
# do something
الأول هو اختبار قيمة منطقية ويمكن تقييمه بالخطأ في سياقات مختلفة.هناك عدد من الأشياء التي تمثل خطأ في اختبارات القيمة المنطقية، على سبيل المثال الحاويات الفارغة والقيم المنطقية.لا يتم تقييم أي شيء أيضًا على أنه خطأ في هذه الحالة ولكن الأشياء الأخرى تفعل ذلك أيضًا.
(ob1 is ob2)
يساوي (id(ob1) == id(ob2))
السبب foo is None
الطريقة المفضلة هي أنك قد تتعامل مع كائن يحدد ما هو خاص به __eq__
, ، وهذا يحدد الكائن بأنه يساوي لا شيء.لذا، استخدم دائمًا foo is None
إذا كنت بحاجة لمعرفة ما إذا كان في الواقع None
.
لا يوجد فرق لأن الأشياء المتطابقة ستكون متساوية بالطبع.لكن، بيب 8 ينص بوضوح على أنه يجب عليك استخدامه is
:
يجب دائمًا إجراء المقارنات مع المفردات مثل لا شيء مع is أو لا، وليس مع عوامل المساواة أبدًا.
is
اختبارات الهوية, لا المساواة.بالنسبة لبيانك foo is none
, تقوم Python ببساطة بمقارنة عنوان ذاكرة الكائنات.هذا يعني أنك تطرح السؤال "هل لدي اسمين لنفس الكائن؟"
==
ومن ناحية أخرى اختبارات المساواة على النحو الذي يحدده __eq__()
طريقة.ولا يهتم بالهوية.
In [102]: x, y, z = 2, 2, 2.0
In [103]: id(x), id(y), id(z)
Out[103]: (38641984, 38641984, 48420880)
In [104]: x is y
Out[104]: True
In [105]: x == y
Out[105]: True
In [106]: x is z
Out[106]: False
In [107]: x == z
Out[107]: True
None
هو مشغل مفرد.لذا None is None
هو دائما صحيح.
In [101]: None is None
Out[101]: True
بالنسبة إلى لا شيء، لا ينبغي أن يكون هناك فرق بين المساواة (==) والهوية (هو).من المحتمل أن يقوم NonType بإرجاع الهوية للمساواة.نظرًا لأن لا شيء هو المثيل الوحيد الذي يمكنك إجراؤه لـ NonType (أعتقد أن هذا صحيح)، فإن العمليتين متماثلتان.في حالة الأنواع الأخرى، ليس هذا هو الحال دائمًا.على سبيل المثال:
list1 = [1, 2, 3]
list2 = [1, 2, 3]
if list1==list2: print "Equal"
if list1 is list2: print "Same"
سيؤدي هذا إلى طباعة "يساوي" نظرًا لأن القوائم تحتوي على عملية مقارنة ليست هي الإرجاع الافتراضي للهوية.
@جيسون:
أوصي باستخدام شيء أكثر على غرار
if foo: #foo isn't None else: #foo is None
لا أحب استخدام "if foo:" إلا إذا كان foo يمثل قيمة منطقية حقًا (على سبيل المثال.0 أو 1).إذا كان foo عبارة عن سلسلة أو كائن أو أي شيء آخر، فقد يعمل "if foo:"، لكنه يبدو وكأنه اختصار بطيء بالنسبة لي.إذا كنت تتحقق لمعرفة ما إذا كانت x لا شيء، فقل "إذا كانت x لا شيء:".
المزيد من التفاصيل:
ال
is
جملة يتحقق في الواقع إذا كان الاثنانobject
S في نفس موقع الذاكرة أم لا.أي ما إذا كان كلاهما يشيران إلى نفس موقع الذاكرة ولديهما نفس الشيءid
.نتيجة لـ 1،
is
يضمن ما إذا كان الاثنان ممثلين معجميًا أم لاobject
s لها سمات متطابقة (سمات السمات...) أم لاإنشاء مثيل للأنواع البدائية مثل
bool
,int
,string
(مع بعض الاستثناءات)،NoneType
سيكون لها نفس القيمة دائمًا في نفس موقع الذاكرة.
على سبيل المثال
>>> int(1) is int(1)
True
>>> str("abcd") is str("abcd")
True
>>> bool(1) is bool(2)
True
>>> bool(0) is bool(0)
True
>>> bool(0)
False
>>> bool(1)
True
ومنذ ذلك الحين NoneType
يمكن أن يكون هناك مثيل واحد فقط لنفسه في جدول "البحث" الخاص ببايثون، وبالتالي فإن الأول والأخير هما أكثر من أسلوب برمجة للمطور الذي كتب الكود (ربما من أجل الاتساق) بدلاً من وجود أي سبب منطقي دقيق لاختيار واحد على الآخر.
استنتاج جون ماشين ذلك None
إن المفردة هي نتيجة يدعمها هذا الكود.
>>> x = None
>>> y = None
>>> x == y
True
>>> x is y
True
>>>
منذ None
هو مفرد، x == None
و x is None
سيكون لها نفس النتيجة.لكن من وجهة نظري الجمالية x == None
هو الأفضل.
a is b # returns true if they a and b are true alias
a == b # returns true if they are true alias or they have values that are deemed equivalence
a = [1,3,4]
b = a[:] #creating copy of list
a is b # if gives false
False
a == b # gives true
True