بررسی عملگر is

سلام به دوستان
وقت بخیر
کد زیر رو دقت کنید که خط آخر جواب True بر می گرداند

a = 2000000
b = 2000000
print(type(a), type(b))
print(id(a), id(b))
print(a is b) # result is True

حالا به کد زیر توجه کنید که جواب False برمی گرداند

a = 2000000
b = 2000000
a_id = id(a)
b_id = id(b)
print(type(a_id), type(b_id))
print(a_id, b_id)
print(a_id is b_id) # result is False

چرا جواب بالا true و جواب پایین false میشه ؟
ممنون میشم کمکم کنید

1 پسندیده

سلام دوست عزیز

  1. کدی فرستادید اشتباه هست (کد اولتونو یبار توی کنسول بزنید …میبنید که False میشه)
  2. علت:
    توی python اعداد 5- تا 256 یک آدرس ثابت دارند ولی اعداد دیگر با یک id دیگر در مموری سیو میشن

اطلاعات بیشتر https://stackoverflow.com/questions/13650293/understanding-pythons-is-operator

ممنون از پاسختون
من کدها ها را بارها چک و اجرا کردم جواب اولی True و جواب دومی False می باشد

1 پسندیده

من هم امتحان کردم هردو False بودن.

البته اگه بنویسیم:

a = b = 2000000
(a is b)

پاسخ True خواهد بود. بنا به یه سری دلایل دیگه.

ممنون از پاسختون
شما توی محیط interactive اجرا می گیرید بهتون False میدهد
اگه توی فایلی بنویسید و اجرا بگیرید True میده
عکس زیر توی vscode هستش که True داده

بقیه ی محیطها هم اصولا باید همین جواب رو بده. پایتون مضخرف هست، ولی نه تا این حد که توی interpreter بخواد duplication داشته باشه.

شاید شما از یه نسخه ی پایتون استفاده میکنید که توی کامپایش فلگهای خاصی روشن بودن. مثلا سایز heap یا همچین چیزی (پایتون stack داره؟) فرق داره.

1 پسندیده

من الآن یه بار دیگه با استفاده از فایل تست کردم و نتیجه‌ی مشابه شما رو گرفتم.

با توجه به تعریف «هرچیزی که میسازیم یه جور آبجکته (ربطی به oop نداره صرفا اسمش اینه) و ۳ تا ویژگی داره. مقدار، نوع و identity. با استفاده از is میتونیم چک کنیم که آیا identity این دوتا آبجکت، دقیقا یکی هست یا نه (آدرسشون توی رم)» (لینک)

با توجه به شناخت کمی که کامپایلرها و مفصرها دارم، سیستم کاریشون اصولا اینطوریه که فایل سورس‌کد ما رو میخونن (انگار یه فایل از روی هارد دیسک میخونن و string دریافت میکنن) و بعد چند مرحله داره از جمله پیدا کردن تابعهایی که اسمشونو بردیم و اختصاص فضای رم به متغیرهایی که ساختیم و بعد هزارتا کار دیگه.
اینطور که به نظر میرسه، پایتون وقتی فایل دریافت میکنه به همین روش عمل میکنه و این مراحل رو به طور کلی برای همه‌ی فایل انجام میده (کل فایل میره توی مرحله‌ی اول بعد نتیجش میره تو مرحله‌ی دوم). پس میتونه duplicationها رو شناسایی کنه و دوتا چیزی که value و type یکسانی دارن رو توی یک مکان از رم (identity) قرار بده.
ولی وقتی از interpreter استفاده میکنیم، این مراحل رو خط به خط اجرا میکنه (یک خط وارد مرحله‌ی اول میشه بعد یک خط دیگه وارد مرحله‌ی دوم میشه) و زمان اجرای هر خط، دیگه نمیاد کد جدید رو با کدهای قبلی مقایسه کنه که شاید value و type یکیشون مثل قبلیا باشه به همون فضا از رم pointer یا همچین چیزی بزنه.

به همین خاطر is توی interpreter خطا میده ولی توی فایل نه.
برای اینکه توی interpreter هم دوتا چیز مشابه، فضای رم مشترک داشته باشن، باید توی یک خط تعریف بشن:

a = b = 2000000

علتش میتونه این باشه که دلشون نمیخواسته موقع کار با interpreter فشار زیادی به cpu بیارن توی پردازش هر خط (و هر خط رو با خطهای بالایی مقایسه کنن) و عوضش به ram فشار بیاد اشکال نداره چون سیستم development هست و فوقش طرف ترمینال رو میبنده دوباره باز میکنه دیگه!


من خیلیوقته از پایتون ناامید شدم ولی اینکه یک ورژنش توی یک سیستم ۲تا رفتار متفاوت داشته باشه، سطح جدیدی از ناامیدی رو نشونم داد.
از اونجایی که این وضعیت از 2.7 بوده و توی 3.7 هم هست، یعنی حس نمیکنن این bug باشه و دلشون نمیخواد فیکسش کنن.


حالا برگردیم سر سوال اول شما.

a = 2000000
b = 2000000
a_id = id(a)
b_id = id(b)
print(type(a_id), type(b_id))
print(a_id, b_id)
print(a_id is b_id) # result is False

به خاطر اینه که is میاد نگاه میکنه ببینه اون دوتا چیز در یک جای رم هستن یا نه.
وقتی شما is رو روی ۲تا متغیر اجرا میکنید، اتفاقی میفته که بالاتر توضیح دادم.
و به نظر میرسه وقتی ما متغیرمون رو به صورت دستی assign نمیکنیم و خروجی id() رو توش میریزیم، مفصر یه جور دیگه assign رو هندل میکنه.

  • چرا؟
    • نمیدونم؟
  • کی میدونه؟
    • اون زمان که داشتن کدش رو مینوشتن، فقط سازنده‌های پایتون و خدا میدونستن. الآن فقط خدا میدونه.
  • این رفتار منطقیه؟
    • مسلما نه.
  • ناامید شدی؟
    • امروز ۲تا سطح جدید از ناامیدی رو کشف کردم.
3 پسندیده

آقای عباسی عزیز خیلی ممنون بابت توضیحات خوبتون
شما از پایتون ناامید شدید اما من چون تازه کارم از فهمیدن یه سری چیزها توی پایتون به وجد میام و لذت می برم

1 پسندیده

برای کامل کردن حرفتون باید بگم interpreter از عدد 5- تا 256 را در یک مکان از رم نگاه می دارد

پایتون زبان خوبیه. مشکلات داره مثل هر زبان دیگه‌ای ولی مسلما جزء top10 هست.
فقط مساله اینه که به در هرکاری نمیخوره، برعکس چیزی که کامیونیتی بهش اعتقاد داره.

لایبرریهای خوبی داره، سرعت نسبتا خوبی داره (اگه هدفمون پردازش موازی نباشه!)، سینتکس نسبتا ساده‌ای داره.
درکل زبان اسکریپت نویسی خوبی هست و احتمالا بهترین زبان برای ساخت پروتوتایپ باشه.
جایگزین مناسبی برای perl هست ولی به درد هر کاری نمیخوره.

1 پسندیده