دوس دارم از این به بعد چیزایی که به نظرم یکم جالب میاد رو بنویسم. زبون پایتون یکی از جذابترین زبونهاس و دونستن نکتههای این زبون هم میتونه واسه کسایی که دوسش دارن جالب باشه. خب حالا که تا اینجا خوندید به نظر شمام پایتون دوس دارید :دی حالا که پایتون دوس دارید به نظرتون خروجی تیکه کد زیر چیه؟
mylist=[] for c in range(3): mylist.append(lambda x:print(x*c, end=',')) for f in mylist: f(True)
ممکنه تو نگاه اول به نظر بیاد که خروجی اینه:
Output: 0,1,2,
اما اینطور نیست! اگه براتون جالبه که بدونید دلیلش چیه، ادامه رو بخونید.
اول یه نکته کوچیک درباره True
و False
توی پایتون بگم. توی python3 مقادیر True
و False
به ترتیب ۱ و ۰ هستن پس ضرب True
در هر عددی همون عدد رو میده.
نکتهای که اینجا وجود داره این هست که ما توی اینجا تنها یه متغیر c
داریم و تابع لامبدا هم قراره ضرب آرگومان ورودیاش با این متغیر c
رو انجام بده اما این تابع لامبدا در اون لحظه صدا زده نشده که مقادیر اصلی بهش وصل بشه و در نتیجه تنها رفرنس متغیر c
هست که توی این تابع باند میشه و تا زمانی که کال نشه ارزیابی نمیشه که مقدارش چی هست. با این تفاسیر، حلقه ما میرسه به آخر و تابع لامبدا رفرنس c
آخرین حلقه رو برای تابع لامبدا در نظر میگیره که مقدار c
آخر ۲ هست.
اگر مقدار رفرنسهای متغیرها رو هم چاپ کنیم میتونیم این رو ببینیم:
mylist=[] for c in range(3): print("c: %s, ID(c): %s" % (c, id(c))) mylist.append(lambda x: print('Value: %s, ID(c): %s, ID(x): %s' % (x*c, id(c), id(x)))) for f in mylist: f(True)
که خروجی به این صورت هست:
c: 0, ID(c): 4304853792 c: 1, ID(c): 4304853824 c: 2, ID(c): 4304853856 <- Reference Value Value: 2, ID(c): 4304853856, ID(x): 4304466784 Value: 2, ID(c): 4304853856, ID(x): 4304466784 Value: 2, ID(c): 4304853856, ID(x): 4304466784
با استفاده از تابع ()id
میتونین مقدار رفرنس متغیرها رو ببینید. همونجوری که توی خروجی میبینید مقداری که داخل لامبدا فانکشن داره استفاده میشه مقدار آخرین رفرنس داخل لوپ یعنی ۲ هست به خاطر همین تمام خروجیها ۲=۲*۱ شده.
خب حالا چیکار کنیم که مقدار c
توی هر لوپ در نظر گرفته بشه و خروجیمون بشه:
Output: 0,1,2,
یه راهش اینه که c
رو از طریق آرگومان پیشفرض (default argument) لامبدا ست کنیم که evaulte بشه و مقدار خودش پاس داده بشه:
mylist=[] for c in range(3): print("c: %s, ID(c): %s" % (c, id(c))) mylist.append(lambda x, c=c: print('Value: %s, ID(c): %s, ID(x): %s' % (x*c, id(c), id(x)))) for f in mylist: f(True)
که خروجی به این صورت میشه:
c: 0, ID(c): 4304853792 c: 1, ID(c): 4304853824 c: 2, ID(c): 4304853856 Value: 0, ID(c): 4304853792, ID(x): 4304466784 Value: 1, ID(c): 4304853824, ID(x): 4304466784 Value: 2, ID(c): 4304853856, ID(x): 4304466784
ایشالا که جذاب بوده باشه براتون و توی کد زدنهاتون در نظر بگیریدش.