"هو" المشغل يتصرف بشكل غير متوقع مع الاعداد الصحيحه

StackOverflow https://stackoverflow.com/questions/306313

سؤال

لماذا التالية تتصرف بشكل غير متوقع في الثعبان ؟

>>> a = 256
>>> b = 256
>>> a is b
True           # This is an expected result
>>> a = 257
>>> b = 257
>>> a is b
False          # What happened here? Why is this False?
>>> 257 is 257
True           # Yet the literal numbers compare properly

أنا باستخدام بيثون 2.5.2.يحاول بعض إصدارات مختلفة من بيثون ، يبدو أن الثعبان 2.3.3 يظهر أعلاه السلوك بين 99 و 100.

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

هل كانت مفيدة؟

المحلول

ونلقي نظرة على هذا:

>>> a = 256
>>> b = 256
>>> id(a)
9987148
>>> id(b)
9987148
>>> a = 257
>>> b = 257
>>> id(a)
11662816
>>> id(b)
11662828

وتحرير: وإليك ما وجدت في وثائق بايثون 2، "كائنات عادي صحيح " (انها الشيء نفسه بالنسبة بيثون 3 ):

<اقتباس فقرة>   

وتنفيذ الحالي يبقي   مجموعة من الكائنات صحيح لجميع   الأعداد الصحيحة بين -5 و 256، عند   إنشاء عدد صحيح في هذا النطاق الذي   في الواقع مجرد نعود إشارة إلى   كائن موجود. لذلك ينبغي أن يكون   يمكن تغيير قيمة 1. I   أظن أن سلوك بيثون في   هذه الحالة هي غير محددة. : -)

نصائح أخرى

بايثون "هو" المشغل يتصرف بشكل غير متوقع مع الاعداد الصحيحه ؟

في ملخص - اسمحوا لي أن أؤكد: لا تستخدم is مقارنة الأعداد الصحيحة.

هذا ليس سلوك يجب أن يكون لديك أي توقعات.

بدلا من, استخدام == و != مقارنة المساواة وعدم المساواة ، على التوالي.على سبيل المثال:

>>> a = 1000
>>> a == 1000       # Test integers like this,
True
>>> a != 5000       # or this!
True
>>> a is 1000       # Don't do this! - Don't use `is` to test integers!!
False

تفسير

أن تعرف هذا, أنت بحاجة إلى معرفته التالية.

أول ما يفعل is تفعل ؟ وهو عامل المقارنة.من الوثائق:

المشغلين is و is not اختبار هوية الكائن: x is y صحيح إذا وفقط إذا x و y هي نفس الكائن. x is not y ينتج معكوس القيمة الحقيقة.

و حتى يلي ما يعادلها.

>>> a is b
>>> id(a) == id(b)

من الوثائق:

id عودة "الهوية" من كائن.هذا هو عدد صحيح (أو طويلة عدد صحيح) وهذا هو ضمان أن تكون فريدة من نوعها و المستمر لهذا الكائن خلال حياته.اثنين من الأشياء مع عدم تداخل عمر قد نفس id() القيمة.

علما أن كون معرف كائن في CPython (الإشارة تنفيذ الثعبان) هو موقع في الذاكرة هو تنفيذ التفاصيل.تطبيقات أخرى من بيثون (مثل Jython أو IronPython) يمكن أن يكون بسهولة تنفيذ مختلف عن id.

فما هو استخدام حدة is? PEP8 يصف:

مقارنات إلى وحدانية مثل None ينبغي دائما أن يتم مع is أو is not, أبدا المساواة بين المشغلين.

السؤال

أنت تسأل و الدولة ، السؤال التالي (مع رمز):

لماذا التالية تتصرف بشكل غير متوقع في الثعبان ؟

>>> a = 256
>>> b = 256
>>> a is b
True           # This is an expected result

فمن لا نتيجة متوقعة.لماذا هو متوقع ؟ بل يعني فقط أن الصحيحه تقدر 256 المشار إليها من قبل كل من a و b هي واحدة من عدد صحيح.الأعداد الصحيحة هي ثابتة في بيثون ، وبالتالي فإنها لا يمكن تغيير.هذا لا يجب أن يؤثر على أي رمز.فإنه لا ينبغي أن يكون متوقعا.هو مجرد تفاصيل التنفيذ.

ولكن ربما يجب أن تكون سعيدة أن هناك ليست جديدة منفصلة سبيل المثال في الذاكرة في كل مرة نقوم الدولة قيمة يساوي 256.

>>> a = 257
>>> b = 257
>>> a is b
False          # What happened here? Why is this False?

يبدو أننا الآن لدينا حالتين منفصلتين من الاعداد الصحيحه مع قيمة 257 في الذاكرة.منذ الأعداد الصحيحة غير قابلة للتغيير ، هذه النفايات الذاكرة.دعونا نأمل أننا لن نضيع الكثير من ذلك.نحن على الأرجح لا.ولكن هذا السلوك غير مضمونة.

>>> 257 is 257
True           # Yet the literal numbers compare properly

حسنا, هذا يبدو وكأنه خاص بك تنفيذ الثعبان تحاول أن تكون ذكية و لا خلق redundantly الكرام الصحيحه في الذاكرة إلا إذا كان لديه.يبدو أنك تشير إلى استخدام المرجع تنفيذ الثعبان الذي هو CPython.جيد CPython.

قد يكون أفضل حتى إذا CPython يمكن أن تفعل هذا على الصعيد العالمي ، إذا كان يمكن أن تفعل ذلك بثمن بخس (كما ستكون هناك تكلفة في البحث) ، وربما آخر قد يؤدي تنفيذها.

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

ما is لا

is يتحقق من أن id اثنين من الأشياء هي نفسها.في CPython ، id هو موقع في الذاكرة ، ولكن يمكن أن يكون بعض فريد تحديد عدد آخر في التنفيذ.أن أكرر هذا مع رمز:

>>> a is b

هو نفس

>>> id(a) == id(b)

لماذا نريد استخدام is بعد ذلك ؟

هذا يمكن أن يكون سريع جدا تحقق نسبة إلى القول التحقق إذا كان اثنين من سلاسل طويلة جدا متساوون في القيمة.ولكن منذ ذلك ينطبق على تفرد من وجوه ، وهكذا لدينا محدودة حالات الاستخدام لذلك.في الواقع, نحن في الغالب ترغب في استخدامه للتحقق من None, الذي هو المفرد (وحيد سبيل المثال الموجودة في مكان واحد في الذاكرة).ونحن قد خلق الأخرى ووحدانية إذا كان هناك إمكانية الخلط بينها ، وهو ما قد تحقق مع is, ولكن هذه هي نادرة نسبيا.هنا مثال (العمل في بيثون 2 و 3) على سبيل المثال

SENTINEL_SINGLETON = object() # this will only be created one time.

def foo(keyword_argument=None):
    if keyword_argument is None:
        print('no argument given to foo')
    bar()
    bar(keyword_argument)
    bar('baz')

def bar(keyword_argument=SENTINEL_SINGLETON):
    # SENTINEL_SINGLETON tells us if we were not passed anything
    # as None is a legitimate potential argument we could get.
    if keyword_argument is SENTINEL_SINGLETON:
        print('no argument given to bar')
    else:
        print('argument to bar: {0}'.format(keyword_argument))

foo()

الذي يطبع:

no argument given to foo
no argument given to bar
argument to bar: None
argument to bar: baz

و لذلك نرى ، is و الحارس, ونحن قادرون على التفريق بين bar بدون وسائط و عندما يتم استدعاء مع None.هذه هي الاستخدام الرئيسي-الحالات is هل لا استخدامها لاختبار المساواة بين الاعداد الصحيحه, سلاسل, الصفوف, أو أشياء أخرى مثل هذه.

وهذا يعتمد على ما إذا كنت تبحث لمعرفة ما إذا كان 2 الأشياء متساوية، أو الكائن نفسه.

والشيكات is لمعرفة ما اذا كانت هي نفس الكائن، وليس فقط على قدم المساواة. ربما كان [إينتس] صغيرة تشير إلى نفس موقع الذاكرة لكفاءة الفضاء

In [29]: a = 3
In [30]: b = 3
In [31]: id(a)
Out[31]: 500729144
In [32]: id(b)
Out[32]: 500729144

ويجب عليك استخدام == مقارنة المساواة بين الأشياء التعسفية. يمكنك تحديد السلوك مع __eq__، والصفات __ne__.

أنا في وقت متأخر، ولكن تريد بعض المصادر مع إجابتك؟ <سوب> *

والشيء الجيد في سي بايثون هو أنه يمكنك فعلا رؤية مصدر لهذا الغرض. انا ذاهب الى استخدام وصلات للإفراج 3.5 في الوقت الراهن. العثور على تلك 2.x المقابلة تافهة.

في سي بايثون، وظيفة C-API الذي يعالج إنشاء كائن int الجديد هو <وأ href = "https://docs.python.org/3/c-api/long.html#c.PyLong_FromLong" يختلط = "noreferrer "> PyLong_FromLong(long v) . وصف لهذه المهمة هو:

<اقتباس فقرة>   

تنفيذ الحالي يحتفظ صفيف من الكائنات صحيح لجميع الأعداد الصحيحة بين -5 و 256، عند إنشاء الباحث في هذا النطاق الذي في الواقع مجرد نعود إشارة إلى كائن موجود . لذلك ينبغي أن يكون من الممكن تغيير قيمة 1. أظن أن سلوك بيثون في هذه الحالة غير معرف. : -)

لا أعرف عنك ولكن أرى أن هذا وفكر! <م> دعونا نجد أن مجموعة

إذا لم مغشوش مع رمز C تنفيذ سي بايثون <م> يجب ، ويتم تنظيم كل شيء جميل ومقروء. لحالتنا، نحن بحاجة الى ان ننظر في الفرعي Objects/ من <ل أ href = "https://hg.python.org/cpython/file/tip" يختلط = "noreferrer"> الرئيسية شفرة المصدر شجرة الدليل .

وصفقات PyLong_FromLong مع كائنات long لذلك لا ينبغي أن يكون من الصعب أن نستنتج أننا بحاجة إلى نظرة خاطفة داخل <لأ href = "https://hg.python.org/cpython/file/tip/Objects/longobject.c" يختلط = "noreferrer"> longobject.c . بعد النظر في داخلك قد يظن الأشياء هي الفوضى. هم، ولكن لا تخف، وظيفة ونحن نبحث عن وتقشعر لها الأبدان في <لأ href = "https://hg.python.org/cpython/file/tip/Objects/longobject.c#l230" يختلط = "noreferrer "> line 230 ينتظرون منا للتحقق من ذلك. انها وظيفة الشريك الأصغر بحيث يتم لصق الجسم الرئيسي (باستثناء الإعلانات) بسهولة هنا:

PyObject *
PyLong_FromLong(long ival)
{
    // omitting declarations

    CHECK_SMALL_INT(ival);

    if (ival < 0) {
        /* negate: cant write this as abs_ival = -ival since that
           invokes undefined behaviour when ival is LONG_MIN */
        abs_ival = 0U-(unsigned long)ival;
        sign = -1;
    }
    else {
        abs_ival = (unsigned long)ival;
    }

    /* Fast path for single-digit ints */
    if (!(abs_ival >> PyLong_SHIFT)) {
        v = _PyLong_New(1);
        if (v) {
            Py_SIZE(v) = sign;
            v->ob_digit[0] = Py_SAFE_DOWNCAST(
                abs_ival, unsigned long, digit);
        }
        return (PyObject*)v; 
}

والآن، نحن لا C <م> السيد ورمز haxxorz ولكن نحن أيضا ليست غبية، يمكننا أن نرى أن CHECK_SMALL_INT(ival); تطل علينا كل مرادفا. يمكننا أن نفهم لديها ما تفعله مع هذا. دعونا التحقق من ذلك:

#define CHECK_SMALL_INT(ival) \
    do if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS) { \
        return get_small_int((sdigit)ival); \
    } while(0)

وحتى انها ماكرو الذي يستدعي وظيفة get_small_int إذا كان ival قيمة تلبي الشرط:

if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS)

فما هي NSMALLNEGINTS وNSMALLPOSINTS؟ إذا كنت تفكر في وحدات الماكرو تحصل على شيء لأنه لم يكن مثل هذا السؤال الصعب .. <م> <وأ href = "https://hg.python.org/cpython/file/tip/Objects/longobject.c#l12" يختلط = "noreferrer"> على أي حال، ها هم :

#ifndef NSMALLPOSINTS
#define NSMALLPOSINTS           257
#endif
#ifndef NSMALLNEGINTS
#define NSMALLNEGINTS           5
#endif

وهكذا شرطنا هو if (-5 <= ival && ival < 257) دعوة get_small_int.

لا مكان آخر للذهاب ولكن نواصل رحلتنا من خلال النظر في get_small_int في كل مجدها (وبشكل جيد، ونحن سوف ننظر فقط في انها الجسم لأن ذلك كان أشياء مثيرة للاهتمام و):

PyObject *v;
assert(-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS);
v = (PyObject *)&small_ints[ival + NSMALLNEGINTS];
Py_INCREF(v);

حسنا، إعلان PyObject، يؤكدون أن حالة السابقة تحمل وتنفيذ المهمة:

v = (PyObject *)&small_ints[ival + NSMALLNEGINTS];

وsmall_ints يتطلع الكثير مثل هذا الصفيف لقد تم البحث عنه .. و، هو! نحن يمكن لقد قرأت للتو وثائق لعنة وكنا 'لقد تعرف على طول :

/* Small integers are preallocated in this array so that they
   can be shared.
   The integers that are preallocated are those in the range
   -NSMALLNEGINTS (inclusive) to NSMALLPOSINTS (not inclusive).
*/
static PyLongObject small_ints[NSMALLNEGINTS + NSMALLPOSINTS];

وهكذا نعم، هذا هو رجلنا. عندما تريد إنشاء int الجديد في مجموعة [NSMALLNEGINTS, NSMALLPOSINTS) عليك فقط نعود إشارة إلى كائن موجود بالفعل تم preallocated.

ومنذ المرجع يشير إلى نفس اوبject، وإصدار id() مباشرة أو التحقق من الهوية مع is على ذلك سيعود بالضبط نفس الشيء.

ولكن، عندما هم المخصصة ؟؟

خلال التهيئة في _PyLong_Init بيثون ستدخل بكل سرور في لحلقة يفعلون ذلك بالنسبة لك:

for (ival = -NSMALLNEGINTS; ival <  NSMALLPOSINTS; ival++, v++) {
    // Look me up!
}

وآمل شرحي جعلت لك C الأشياء (التورية الواضح intented) بشكل واضح الآن.


ولكن، 257 هو 257؟ ما الأمر؟

وهذا هو في الواقع أسهل للشرح، وحاولت أن تفعل ذلك بالفعل . انها يرجع ذلك إلى حقيقة أن بيثون سيتم تنفيذ هذا البيان التفاعلية:

>>> 257 is 257

وككتلة واحدة. خلال complilation هذا البيان، سوف سي بايثون نرى أن لديك اثنين من حرفية مطابقة وسوف تستخدم نفس PyLongObject تمثل 257. يمكنك ان ترى هذا إذا كنت تفعل تجميع نفسك وفحص محتوياته:

>>> codeObj = compile("257 is 257", "blah!", "exec")
>>> codeObj.co_consts
(257, None)

ومتى سي بايثون العملية؛ انها الآن مجرد الذهاب لتحميل نفس الكائن المحدد:

>>> import dis
>>> dis.dis(codeObj)
  1           0 LOAD_CONST               0 (257)   # dis
              3 LOAD_CONST               0 (257)   # dis again
              6 COMPARE_OP               8 (is)

وهكذا is سيعود True.


<الفرعية> * - سأحاول وكلمة هذا بطريقة أكثر التمهيدية من أجل معظم لتكون قادرة على متابعة طول

وكما يمكنك أن تحقق في الملف المصدر <م> intobject.c ، بيثون تخزين الأعداد الصحيحة صغيرة للكفاءة. في كل مرة تقوم بإنشاء إشارة إلى عدد صحيح صغير، كنت تشير إلى عدد صحيح صغير مؤقتا، وليس كائن جديد. 257 ليس صحيحا صغير، لذلك يتم احتساب أنها كائن آخر.

ومن الأفضل استخدام == لهذا الغرض.

وأعتقد الفرضيات الخاصة بك هو الصحيح. التجربة مع id (هوية الكائن):

In [1]: id(255)
Out[1]: 146349024

In [2]: id(255)
Out[2]: 146349024

In [3]: id(257)
Out[3]: 146802752

In [4]: id(257)
Out[4]: 148993740

In [5]: a=255

In [6]: b=255

In [7]: c=257

In [8]: d=257

In [9]: id(a), id(b), id(c), id(d)
Out[9]: (146349024, 146349024, 146783024, 146804020)

ويبدو أن الأرقام <= 255 تعامل على أنها الحرفية ويعامل أي شيء فوق بشكل مختلف!

لكائنات قيمة ثابتة، مثل [إينتس]، سلاسل أو datetimes، هوية الكائن ليست مفيدة بشكل خاص. فمن الأفضل أن نفكر في المساواة. الهوية هي في الأساس عملية تفصيل تطبيق للكائنات القيمة - حيث انهم غير قابل للتغيير، وليس هناك فرق بين وجود فعال الحكام متعددة لنفس الكائن أو الكائنات متعددة

وis <م> هو المشغل المساواة الهوية (تعمل مثل id(a) == id(b))؛ انها مجرد أن اثنين من أعداد متساوية ليست بالضرورة هي نفس الكائن. لأسباب تتعلق بالأداء بعض الأعداد الصحيحة صغيرة يحدث أن تكون memoized حتى انهم سوف تميل إلى أن تكون هي نفسها (وهذا يمكن يتعين القيام به لأنها غير قابلة للتغيير).

مشغل === PHP، وعلى الجانب الآخر، يوصف بأنه فحص المساواة ونوع: x == y and type(x) == type(y) وفقا لتعليق باولو فريتاس ". وهذا يكفي لأعداد مشتركة، ولكن تختلف من is لفئات التي تحدد __eq__ بطريقة سخيفة:

class Unequal:
    def __eq__(self, other):
        return False

وPHP على ما يبدو تسمح نفس الشيء لفئات "المدمج في" (التي تتخذ ليعني تنفيذها على المستوى C، وليس في PHP). واستخدام أقل قليلا من السخف قد يكون كائن مؤقت، والتي لديها قيمة مختلفة في كل مرة انها تستخدم كرقم. تماما لماذا كنت تريد محاكاة البصرية Now الأساسية بدلا من تبين أنه هو التقييم مع time.time() أنا لا أعرف.

وقدم جريج Hewgill (OP) واحدة توضيح تعليق "هدفي هو مقارنة هوية الكائن، بدلا من المساواة في القيمة. وفيما عدا الأرقام، حيث أريد لعلاج هوية الكائن في نفس المساواة في القيمة."

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

ويمكننا محاولة استخدام isinstance مع جميع أنواع العدد نعرف، ولكن هذا سيكون حتما غير مكتملة. تحتوي وحدة قائمة أنواع StringTypes لكن لا NumberTypes. منذ بايثون 2.6، المدمج في صفوف عدد يملك الفئة الأساسية numbers.Number ، لكنه لا يملك نفس المشكلة:

import numpy, numbers
assert not issubclass(numpy.int16,numbers.Number)
assert issubclass(int,numbers.Number)

وبالمناسبة، نمباي سوف تنتج حالات منفصلة من أرقام منخفضة.

وأنا لا أعرف في الواقع جوابا على هذا الخيار غير وارد. أفترض يمكن للمرء أن نظريا استخدام ctypes للاتصال PyNumber_Check، ولكن حتى تلك الوظيفة وقد ناقش ، وانها بالتأكيد ليست المحمولة. فما علينا إلا أن يكون أقل خصوصا حول ما نقوم اختبار في الوقت الراهن.

في النهاية، وتنبع هذه المسألة من بيثون عدم وجود أصلا شجرة نوع مع المسندات مثل مخطط ل number?، أو هاسكل في <لأ href = "الشبكي: / /en.wikipedia.org/wiki/Type_class "يختلط =" نوفولو "> نوع فئة <لأ href =" http://www.haskell.org/ghc/docs/7.4-latest/html/libraries/ قاعدة 4.5.1.0 / Prelude.html # ر: ارقام "يختلط =" نوفولو "> الصيغة الرقميه . كائن الشيكات is المساواة الهوية، وليس القيمة. PHP لديها تاريخ الملونة أيضا، حيث يبدو يتصرف === كما is فقط على الأشياء في PHP5، ولكن ليس PHP4 . مثل هي آلام النمو الانتقال عبر لغات (بما في ذلك إصدارات واحد).

هناك مسألة أخرى لا يشير في أي من الإجابات.بيثون يسمح لدمج أي اثنين من القيم الراسخة ، التي تم إنشاؤها مسبقا صغيرة الباحث القيم ليست الطريقة الوحيدة التي يمكن أن يحدث هذا.الثعبان تنفيذ أبدا مضمونة للقيام بذلك, لكنها تفعل كل ذلك على أكثر من مجرد صغيرة رجات.


لشيء واحد, هناك بعض أخرى قبل خلق القيم ، مثل فارغة tuple, str, ، bytes, و بعض سلاسل قصيرة (في CPython 3.6 انه 256 حرف واحد اللاتينية-1 السلاسل).على سبيل المثال:

>>> a = ()
>>> b = ()
>>> a is b
True

ولكن أيضا حتى غير قبل خلق القيم يمكن أن تكون متطابقة.النظر في هذه الأمثلة:

>>> c = 257
>>> d = 257
>>> c is d
False
>>> e, f = 258, 258
>>> e is f
True

و هذا لا يقتصر على int القيم:

>>> g, h = 42.23e100, 42.23e100
>>> g is h
True

ومن الواضح CPython لا يأتي مع إنشاؤها مسبقا float قيمة 42.23e100.لذا, ما الذي يجري هنا ؟

على CPython المترجم دمج قيم ثابتة من بعض معروف-غير قابل للتغيير أنواع مثل int, float, str, bytes, في نفس تجميع وحدة.من أجل وحدة, كل وحدة تجميع وحدة ولكن في التفاعلية مترجم, كل بيان منفصل تجميع وحدة.منذ c و d محددة في بيانات منفصلة ، القيم ليست دمجها.منذ e و f يتم تعريف في نفس البيان ، قيمها المدمجة.


يمكنك أن ترى ما يجري من تفكيك بايت كود.محاولة تحديد وظيفة لا e, f = 128, 128 ثم يدعو dis.dis و سترى أن هناك واحد قيمة ثابتة (128, 128)

>>> def f(): i, j = 258, 258
>>> dis.dis(f)
  1           0 LOAD_CONST               2 ((128, 128))
              2 UNPACK_SEQUENCE          2
              4 STORE_FAST               0 (i)
              6 STORE_FAST               1 (j)
              8 LOAD_CONST               0 (None)
             10 RETURN_VALUE
>>> f.__code__.co_consts
(None, 128, (128, 128))
>>> id(f.__code__.co_consts[1], f.__code__.co_consts[2][0], f.__code__.co_consts[2][1])
4305296480, 4305296480, 4305296480

قد تلاحظ أن المترجم له المخزنة 128 كما مستمر على الرغم من انها لا تستخدم بالفعل من قبل بايت كود, والتي تعطيك فكرة عن كيفية الصغير الأمثل CPython برنامج التحويل البرمجي لا.وهو ما يعني أن (غير فارغة) الصفوف في الواقع لا نهاية المطاف اندمجت:

>>> k, l = (1, 2), (1, 2)
>>> k is l
False

ضع هذا في وظيفة ، dis ننظر في co_consts—هناك 1 و 2, اثنين (1, 2) المجموعات التي تشترك في نفس 1 و 2 ولكن ليست متطابقة ، ((1, 2), (1, 2)) المجموعة التي لديها اثنين متميزة تكافؤ المجموعات.


هناك أكثر من الأمثل أن CPython لا:سلسلة التدريب.على عكس مترجم ثابتة قابلة للطي, هذا لا يقتصر البرمجية المصدر حرفية:

>>> m = 'abc'
>>> n = 'abc'
>>> m is n
True

من ناحية أخرى, فإنه يقتصر على str نوع و سلاسل من تخزين داخلية من نوع "ascii المدمجة", "المدمجة" ، أو "إرث جاهزة", و في كثير من الحالات فقط "ascii" الميثاق سوف تحصل على المعتقلين.


على أي حال, قواعد القيم ما يجب أن يكون, قد تكون أو لا تكون متميزة تختلف من تنفيذ التنفيذ ، و بين إصدارات من نفس التنفيذ ، وربما حتى بين أشواط من نفس القانون على نفس نسخة من نفس التنفيذ.

فإنه يمكن أن يكون من المفيد تعلم قواعد محددة الثعبان من أجل المتعة.لكن الأمر لا يستحق الاعتماد عليها في التعليمات البرمجية الخاصة بك.الوحيد الآمن القاعدة:

  • لا كتابة التعليمات البرمجية التي يفترض اثنين متساوية ولكن بشكل منفصل-خلق قيم ثابتة متطابقة.
  • لا كتابة التعليمات البرمجية التي يفترض اثنين متساوية ولكن بشكل منفصل-خلق قيم ثابتة متميزة.

أو بعبارة أخرى فقط استخدام is لاختبار موثقة ووحدانية (مثل None) أو التي يتم إنشاؤها فقط في مكان واحد في التعليمات البرمجية (مثل _sentinel = object() لغة).

ويحدث ذلك أيضا مع سلاسل:

>>> s = b = 'somestr'
>>> s == b, s is b, id(s), id(b)
(True, True, 4555519392, 4555519392)

والآن يبدو أن كل شيء على ما يرام.

>>> s = 'somestr'
>>> b = 'somestr'
>>> s == b, s is b, id(s), id(b)
(True, True, 4555519392, 4555519392)

وهذا من المتوقع أيضا.

>>> s1 = b1 = 'somestrdaasd ad ad asd as dasddsg,dlfg ,;dflg, dfg a'
>>> s1 == b1, s1 is b1, id(s1), id(b1)
(True, True, 4555308080, 4555308080)

>>> s1 = 'somestrdaasd ad ad asd as dasddsg,dlfg ,;dflg, dfg a'
>>> b1 = 'somestrdaasd ad ad asd as dasddsg,dlfg ,;dflg, dfg a'
>>> s1 == b1, s1 is b1, id(s1), id(b1)
(True, False, 4555308176, 4555308272)

والآن هذا غير متوقع.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top