You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
پس بیثباتی تو این رفتار به خاطر اینه که مقدار `another_ordered_dict in another_set` برابر با `False` هست چون `ordered_dict` از قبل داخل `another_set` هست و همونطور که قبلا مشاهده کردید، مقدار `ordered_dict == another_ordered_dict` برابر با `False` هست.
589
590
590
591
---
@@ -788,3 +789,219 @@ False
788
789
- در مثال بالا، عبارت `(not None)` برابره با مقدار `True` از اونجایی که مقدار `None` در زمینه boolean به `False` تبدیل میشه. پس کل عبارت معادل عبارت `'something' is True` میشه.
789
790
790
791
---
792
+
793
+
794
+
### ▶ یک بازی دوز که توش X همون اول برنده میشه!
795
+
<!-- Example ID: 69329249-bdcb-424f-bd09-cca2e6705a7a --->
796
+
797
+
```py
798
+
# بیاید یک سطر تشکیل بدیم
799
+
row = [""] *3#row i['', '', '']
800
+
# حالا بیاید تخته بازی رو ایجاد کنیم
801
+
board = [row] *3
802
+
```
803
+
804
+
**خروجی:**
805
+
806
+
```py
807
+
>>> board
808
+
[['', '', ''], ['', '', ''], ['', '', '']]
809
+
>>> board[0]
810
+
['', '', '']
811
+
>>> board[0][0]
812
+
''
813
+
>>> board[0][0] ="X"
814
+
>>> board
815
+
[['X', '', ''], ['X', '', ''], ['X', '', '']]
816
+
```
817
+
818
+
ما که سهتا `"X"` نذاشتیم. گذاشتیم مگه؟
819
+
820
+
#### 💡 توضیحات:
821
+
822
+
وقتی متغیر `row` رو تشکیل میدیم، تصویر زیر نشون میده که چه اتفاقی در حافظه دستگاه میافته.
<img alt="Shows a memory segment after row is initialized." src="/images/tic-tac-toe/after_row_initialized.svg">
829
+
</picture>
830
+
</p>
831
+
832
+
و وقتی متغیر `board` رو با ضرب کردن متغیر `row` تشکیل میدیم، تصویر زیر به صورت کلی نشون میده که چه اتفاقی در حافظه میافته (هر کدوم از عناصر `board[0]`، `board[1]` و `board[2]` در حافظه به لیست یکسانی به نشانی `row` اشاره میکنند).
<img alt="Shows a memory segment after board is initialized." src="/images/tic-tac-toe/after_board_initialized.svg">
839
+
</picture>
840
+
</p>
841
+
842
+
ما میتونیم با استفاده نکردن از متغیر `row` برای تولید متغیر `board` از این سناریو پرهیز کنیم. (در [این](https://github.com/satwikkansal/wtfpython/issues/68) موضوع پرسیده شده).
843
+
844
+
```py
845
+
>>> board = [['']*3for _ inrange(3)]
846
+
>>> board[0][0] ="X"
847
+
>>> board
848
+
[['X', '', ''], ['', '', ''], ['', '', '']]
849
+
```
850
+
851
+
---
852
+
853
+
854
+
### ▶ متغیر شرودینگر *
855
+
<!-- Example ID: 4dc42f77-94cb-4eb5-a120-8203d3ed7604 --->
856
+
857
+
858
+
```py
859
+
funcs = []
860
+
results = []
861
+
for x inrange(7):
862
+
defsome_func():
863
+
return x
864
+
funcs.append(some_func)
865
+
results.append(some_func()) # note the function call here
866
+
867
+
funcs_results = [func() for func in funcs]
868
+
```
869
+
870
+
**خروجی:**
871
+
```py
872
+
>>> results
873
+
[0, 1, 2, 3, 4, 5, 6]
874
+
>>> funcs_results
875
+
[6, 6, 6, 6, 6, 6, 6]
876
+
```
877
+
878
+
مقدار `x` در هر تکرار حلقه قبل از اضافه کردن `some_func` به لیست `funcs` متفاوت بود، ولی همه توابع در خارج از حلقه مقدار `6` رو برمیگردونند.
879
+
880
+
2.
881
+
882
+
```py
883
+
>>> powers_of_x = [lambdax: x**i for i inrange(10)]
* وقتی یک تابع رو در داخل یک حلقه تعریف میکنیم که در بدنهاش از متغیر اون حلقه استفاده شده، بست این تابع به *متغیر* وصله، نه *مقدار* اون. تابع به جای اینکه از مقدار `x` در زمان تعریف تابع استفاده کنه، در زمینه اطرافش دنبال `x` میگرده. پس همه این توابع از آخرین مقداری که به متغیر `x` مقداردهی شده برای محاسباتشون استفاده میکنند. ما میتونیم ببینیم که این توابع از متغیر `x` که در زمینه اطرافشون (*نه* از متغیر محلی) هست، استفاده میکنند، به این صورت:
از اونجایی که `x` یک متغیر سراسریه (گلوبال)، ما میتونیم مقداری که توابع داخل `funcs` دنبالشون میگردند و برمیگردونند رو با بهروز کردن `x` تغییر بدیم:
898
+
899
+
```py
900
+
>>> x =42
901
+
>>> [func() for func in funcs]
902
+
[42, 42, 42, 42, 42, 42, 42]
903
+
```
904
+
905
+
* برای رسیدن به رفتار موردنظر شما میتونید متغیر حلقه رو به عنوان یک متغیر اسمدار به تابع بدید. **چرا در این صورت کار میکنه؟** چون اینجوری یک متغیر در دامنه خود تابع تعریف میشه. تابع دیگه دنبال مقدار `x` در دامنه اطراف (سراسری) نمیگرده ولی یک متغیر محلی برای ذخیره کردن مقدار `x` در اون لحظه میسازه.
906
+
907
+
```py
908
+
funcs = []
909
+
for x inrange(7):
910
+
defsome_func(x=x):
911
+
return x
912
+
funcs.append(some_func)
913
+
```
914
+
915
+
**خروجی:**
916
+
917
+
```py
918
+
>>> funcs_results = [func() for func in funcs]
919
+
>>> funcs_results
920
+
[0, 1, 2, 3, 4, 5, 6]
921
+
```
922
+
923
+
دیگه از متغیر `x` در دامنه سراسری استفاده نمیکنه:
<!-- Example ID: 60730dc2-0d79-4416-8568-2a63323b3ce8 --->
935
+
1\.
936
+
```py
937
+
>>>isinstance(3, int)
938
+
True
939
+
>>>isinstance(type, object)
940
+
True
941
+
>>>isinstance(object, type)
942
+
True
943
+
```
944
+
945
+
پس کدوم کلاس پایه "نهایی" هست؟ راستی سردرگمی بیشتری هم تو راهه.
946
+
947
+
2\.
948
+
949
+
```py
950
+
>>>classA: pass
951
+
>>>isinstance(A, A)
952
+
False
953
+
>>>isinstance(type, type)
954
+
True
955
+
>>>isinstance(object, object)
956
+
True
957
+
```
958
+
959
+
3\.
960
+
961
+
```py
962
+
>>>issubclass(int, object)
963
+
True
964
+
>>>issubclass(type, object)
965
+
True
966
+
>>>issubclass(object, type)
967
+
False
968
+
```
969
+
970
+
971
+
#### 💡 توضیحات
972
+
973
+
- در پایتون، `type` یک [متاکلاس](https://realpython.com/python-metaclasses/) است.
974
+
- در پایتون **همه چیز** یک `object` است، که کلاسها و همچنین نمونههاشون (یا همان instance های کلاسها) هم شامل این موضوع میشن.
975
+
- کلاس `type` یک متاکلاسه برای کلاس `object` و همه کلاسها (همچنین کلاس `type`) به صورت مستقیم یا غیرمستقیم از کلاس `object` ارث بری کرده است.
976
+
- هیچ کلاس پایه واقعی بین کلاسهای `object` و `type` وجود نداره. سردرگمی که در قطعهکدهای بالا به وجود اومده، به خاطر اینه که ما به این روابط (یعنی `issubclass` و `isinstance`) از دیدگاه کلاسهای پایتون فکر میکنیم. رابطه بین `object` و `type` رو در پایتون خالص نمیشه بازتولید کرد. برای اینکه دقیقتر باشیم، رابطههای زیر در پایتون خالص نمیتونند بازتولید بشن.
977
+
+ کلاس A یک نمونه از کلاس B، و کلاس B یک نمونه از کلاس A باشه.
978
+
+ کلاس A یک نمونه از خودش باشه.
979
+
-
980
+
- این روابط بین `object` و `type` (که هردو نمونه یکدیگه و همچنین خودشون باشند) به خاطر "تقلب" در مرحله پیادهسازی، وجود دارند.
981
+
982
+
---
983
+
984
+
985
+
### ▶ روابط بین زیرمجموعه کلاسها
986
+
<!-- Example ID: 9f6d8cf0-e1b5-42d0-84a0-4cfab25a0bc0 --->
987
+
**خروجی:**
988
+
```py
989
+
>>>from collections.abc import Hashable
990
+
>>>issubclass(list, object)
991
+
True
992
+
>>>issubclass(object, Hashable)
993
+
True
994
+
>>>issubclass(list, Hashable)
995
+
False
996
+
```
997
+
998
+
ما انتظار داشتیم که روابط بین زیرکلاسها، انتقالی باشند، درسته؟ (یعنی اگه `A` زیرکلاس `B` باشه و `B` هم زیرکلاس `C` باشه، کلس `A`__باید__ زیرکلاس `C` باشه)
999
+
1000
+
#### 💡 توضیحات:
1001
+
1002
+
* روابط بین زیرکلاسها در پایتون لزوما انتقالی نیستند. همه مجازند که تابع `__subclasscheck__` دلخواه خودشون رو در یک متاکلاس تعریف کنند.
1003
+
* وقتی عبارت `issubclass(cls, Hashable)` اجرا میشه، برنامه دنبال یک تابع "غیر نادرست" (یا non-Falsy) در `cls` یا هرچیزی که ازش ارثبری میکنه، میگرده.
1004
+
* از اونجایی که `object` قابل هش شدنه، ولی `list` اینطور نیست، رابطه انتقالی شکسته میشه.
1005
+
* توضیحات با جزئیات بیشتر [اینجا](https://www.naftaliharris.com/blog/python-subclass-intransitivity/) پیدا میشه.
0 commit comments