mirror of
https://github.com/satwikkansal/wtfpython
synced 2025-05-19 18:53:46 +02:00
update farsi translation - section 1
This commit is contained in:
parent
6592360507
commit
4d8e193d65
298
translations/fa-farsi/section1-temp.md
vendored
298
translations/fa-farsi/section1-temp.md
vendored
@ -490,3 +490,301 @@ True
|
||||
همونطور که مشاهده میکنید، ترتیب حذف شدن شیءها باعث تفاوت میشه.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### ▶ بینظمی در خود نظم *
|
||||
<!-- Example ID: 91bff1f8-541d-455a-9de4-6cd8ff00ea66 --->
|
||||
```py
|
||||
from collections import OrderedDict
|
||||
|
||||
dictionary = dict()
|
||||
dictionary[1] = 'a'; dictionary[2] = 'b';
|
||||
|
||||
ordered_dict = OrderedDict()
|
||||
ordered_dict[1] = 'a'; ordered_dict[2] = 'b';
|
||||
|
||||
another_ordered_dict = OrderedDict()
|
||||
another_ordered_dict[2] = 'b'; another_ordered_dict[1] = 'a';
|
||||
|
||||
class DictWithHash(dict):
|
||||
"""
|
||||
یک dict که تابع جادویی __hash__ هم توش پیاده شده.
|
||||
"""
|
||||
__hash__ = lambda self: 0
|
||||
|
||||
class OrderedDictWithHash(OrderedDict):
|
||||
"""
|
||||
یک OrderedDict که تابع جادویی __hash__ هم توش پیاده شده.
|
||||
"""
|
||||
__hash__ = lambda self: 0
|
||||
```
|
||||
|
||||
**Output**
|
||||
```py
|
||||
>>> dictionary == ordered_dict # اگر مقدار اولی با دومی برابره
|
||||
True
|
||||
>>> dictionary == another_ordered_dict # و مقدار اولی با سومی برابره
|
||||
True
|
||||
>>> ordered_dict == another_ordered_dict # پس چرا مقدار دومی با سومی برابر نیست؟
|
||||
False
|
||||
|
||||
# ما همهمون میدونیم که یک مجموعه فقط شامل عناصر منحصربهفرد و غیرتکراریه.
|
||||
# بیاید یک مجموعه از این دیکشنریها بسازیم ببینیم چه اتفاقی میافته...
|
||||
|
||||
>>> len({dictionary, ordered_dict, another_ordered_dict})
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in <module>
|
||||
TypeError: unhashable type: 'dict'
|
||||
|
||||
# منطقیه چون dict ها __hash__ توشون پیادهسازی نشده. پس بیاید از
|
||||
# کلاسهایی که خودمون درست کردیم استفاده کنیم.
|
||||
>>> dictionary = DictWithHash()
|
||||
>>> dictionary[1] = 'a'; dictionary[2] = 'b';
|
||||
>>> ordered_dict = OrderedDictWithHash()
|
||||
>>> ordered_dict[1] = 'a'; ordered_dict[2] = 'b';
|
||||
>>> another_ordered_dict = OrderedDictWithHash()
|
||||
>>> another_ordered_dict[2] = 'b'; another_ordered_dict[1] = 'a';
|
||||
>>> len({dictionary, ordered_dict, another_ordered_dict})
|
||||
1
|
||||
>>> len({ordered_dict, another_ordered_dict, dictionary}) # ترتیب رو عوض میکنیم
|
||||
2
|
||||
```
|
||||
|
||||
چی شد؟
|
||||
|
||||
#### 💡 توضیحات:
|
||||
|
||||
- دلیل اینکه این مقایسه بین متغیرهای `dictionary`، `ordered_dict` و `another_ordered_dict` به درستی اجرا نمیشه به خاطر نحوه پیادهسازی تابع `__eq__` در کلاس `OrderedDict` هست. طبق [مستندات](https://docs.python.org/3/library/collections.html#ordereddict-objects)
|
||||
> مقایسه برابری بین شیءهایی از نوع OrderedDict به ترتیب اعضای آنها هم بستگی دارد و به صورت `list(od1.items())==list(od2.items())` پیاده سازی شده است. مقایسه برابری بین شیءهای `OrderedDict` و شیءهای قابل نگاشت دیگر به ترتیب اعضای آنها بستگی ندارد و مقایسه همانند دیکشنریهای عادی انجام میشود.
|
||||
- این رفتار باعث میشه که بتونیم `OrderedDict` ها رو هرجایی که یک دیکشنری عادی کاربرد داره، جایگزین کنیم و استفاده کنیم.
|
||||
- خب، حالا چرا تغییر ترتیب روی طول مجموعهای که از دیکشنریها ساختیم، تاثیر گذاشت؟ جوابش همین رفتار مقایسهای غیرانتقالی بین این شیءهاست. از اونجایی که `set` ها مجموعهای از عناصر غیرتکراری و بدون نظم هستند، ترتیبی که عناصر تو این مجموعهها درج میشن نباید مهم باشه. ولی در این مورد، مهم هست. بیاید کمی تجزیه و تحلیلش کنیم.
|
||||
```py
|
||||
>>> some_set = set()
|
||||
>>> some_set.add(dictionary) # این شیءها از قطعهکدهای بالا هستند.
|
||||
>>> ordered_dict in some_set
|
||||
True
|
||||
>>> some_set.add(ordered_dict)
|
||||
>>> len(some_set)
|
||||
1
|
||||
>>> another_ordered_dict in some_set
|
||||
True
|
||||
>>> some_set.add(another_ordered_dict)
|
||||
>>> len(some_set)
|
||||
1
|
||||
|
||||
>>> another_set = set()
|
||||
>>> another_set.add(ordered_dict)
|
||||
>>> another_ordered_dict in another_set
|
||||
False
|
||||
>>> another_set.add(another_ordered_dict)
|
||||
>>> len(another_set)
|
||||
2
|
||||
>>> dictionary in another_set
|
||||
True
|
||||
>>> another_set.add(another_ordered_dict)
|
||||
>>> len(another_set)
|
||||
2
|
||||
```
|
||||
پس بیثباتی تو این رفتار به خاطر اینه که مقدار `another_ordered_dict in another_set` برابر با `False` هست چون `ordered_dict` از قبل داخل `another_set` هست و همونطور که قبلا مشاهده کردید، مقدار `ordered_dict == another_ordered_dict` برابر با `False` هست.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### ▶ تلاش کن... *
|
||||
<!-- Example ID: b4349443-e89f-4d25-a109-82616be9d41a --->
|
||||
```py
|
||||
def some_func():
|
||||
try:
|
||||
return 'from_try'
|
||||
finally:
|
||||
return 'from_finally'
|
||||
|
||||
def another_func():
|
||||
for _ in range(3):
|
||||
try:
|
||||
continue
|
||||
finally:
|
||||
print("Finally!")
|
||||
|
||||
def one_more_func():
|
||||
try:
|
||||
for i in range(3):
|
||||
try:
|
||||
1 / i
|
||||
except ZeroDivisionError:
|
||||
# بذارید اینجا ارور بدیم و بیرون حلقه بهش
|
||||
# رسیدگی کنیم
|
||||
raise ZeroDivisionError("A trivial divide by zero error")
|
||||
finally:
|
||||
print("Iteration", i)
|
||||
break
|
||||
except ZeroDivisionError as e:
|
||||
print("Zero division error occurred", e)
|
||||
```
|
||||
|
||||
**خروجی:**
|
||||
|
||||
```py
|
||||
>>> some_func()
|
||||
'from_finally'
|
||||
|
||||
>>> another_func()
|
||||
Finally!
|
||||
Finally!
|
||||
Finally!
|
||||
|
||||
>>> 1 / 0
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in <module>
|
||||
ZeroDivisionError: division by zero
|
||||
|
||||
>>> one_more_func()
|
||||
Iteration 0
|
||||
|
||||
```
|
||||
|
||||
#### 💡 Explanation:
|
||||
|
||||
- وقتی یک عبارت `return`، `break` یا `continue` داخل بخش `try` از یک عبارت "try...finally" اجرا میشه، بخش `fianlly` هم هنگام خارج شدن اجرا میشه.
|
||||
- مقدار بازگشتی یک تابع از طریق آخرین عبارت `return` که داخل تابع اجرا میشه، مشخص میشه. از اونجایی که بخش `finally` همیشه اجرا میشه، عبارت `return` که داخل بخش `finally` هست آخرین عبارتیه که اجرا میشه.
|
||||
- نکته اینجاست که اگه بخش داخل بخش `finally` یک عبارت `return` یا `break` اجرا بشه، `exception` موقتی که ذخیره شده، رها میشه.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### ▶ برای چی?
|
||||
<!-- Example ID: 64a9dccf-5083-4bc9-98aa-8aeecde4f210 --->
|
||||
```py
|
||||
some_string = "wtf"
|
||||
some_dict = {}
|
||||
for i, some_dict[i] in enumerate(some_string):
|
||||
i = 10
|
||||
```
|
||||
|
||||
**Output:**
|
||||
```py
|
||||
>>> some_dict # یک دیکشنری مرتبشده نمایان میشه.
|
||||
{0: 'w', 1: 't', 2: 'f'}
|
||||
```
|
||||
|
||||
#### 💡 توضیحات:
|
||||
* یک حلقه `for` در [گرامر پایتون](https://docs.python.org/3/reference/grammar.html) این طور تعریف میشه:
|
||||
```
|
||||
for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]
|
||||
```
|
||||
به طوری که `exprlist` یک هدف برای مقداردهیه. این یعنی، معادل عبارت `{exprlist} = {next_value}` **برای هر شیء داخل `testlist` اجرا میشود**.
|
||||
یک مثال جالب برای نشون دادن این تعریف:
|
||||
```py
|
||||
for i in range(4):
|
||||
print(i)
|
||||
i = 10
|
||||
```
|
||||
|
||||
**خروجی:**
|
||||
```
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
```
|
||||
|
||||
آیا انتظار داشتید که حلقه فقط یک بار اجرا بشه؟
|
||||
|
||||
**💡 توضیحات:**
|
||||
|
||||
- عبارت مقداردهی `i = 10` به خاطر نحوه کار کردن حلقهها، هیچوقت باعث تغییر در تکرار حلقه نمیشه. قبل از شروع هر تکرار، مقدار بعدی که توسط شیء قابل تکرار (که در اینجا `range(4)` است) ارائه میشه، از بسته خارج میشه و به متغیرهای لیست هدف (که در اینجا `i` است) مقداردهی میشه.
|
||||
|
||||
* تابع `enumerate(some_string)`، یک متغیر `i` (که یک شمارنده اقزایشی است) و یک حرف از حروف رشته `some_string` رو در هر تکرار برمیگردونه. و بعدش برای کلید `i` (تازه مقداردهیشده) در دیکشنری `some_dict`، مقدار اون حرف رو تنظیم میکنه. بازشده این حلقه میتونه مانند مثال زیر ساده بشه:
|
||||
```py
|
||||
>>> i, some_dict[i] = (0, 'w')
|
||||
>>> i, some_dict[i] = (1, 't')
|
||||
>>> i, some_dict[i] = (2, 'f')
|
||||
>>> some_dict
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### ▶ اختلاف زمانی در محاسبه
|
||||
<!-- Example ID: 6aa11a4b-4cf1-467a-b43a-810731517e98 --->
|
||||
1\.
|
||||
```py
|
||||
array = [1, 8, 15]
|
||||
# یک عبارت تولیدکننده عادی
|
||||
gen = (x for x in array if array.count(x) > 0)
|
||||
array = [2, 8, 22]
|
||||
```
|
||||
|
||||
**خروجی:**
|
||||
|
||||
```py
|
||||
>>> print(list(gen)) # پس بقیه مقدارها کجا رفتن؟
|
||||
[8]
|
||||
```
|
||||
|
||||
2\.
|
||||
|
||||
```py
|
||||
array_1 = [1,2,3,4]
|
||||
gen_1 = (x for x in array_1)
|
||||
array_1 = [1,2,3,4,5]
|
||||
|
||||
array_2 = [1,2,3,4]
|
||||
gen_2 = (x for x in array_2)
|
||||
array_2[:] = [1,2,3,4,5]
|
||||
```
|
||||
|
||||
**خروجی:**
|
||||
```py
|
||||
>>> print(list(gen_1))
|
||||
[1, 2, 3, 4]
|
||||
|
||||
>>> print(list(gen_2))
|
||||
[1, 2, 3, 4, 5]
|
||||
```
|
||||
|
||||
3\.
|
||||
|
||||
```py
|
||||
array_3 = [1, 2, 3]
|
||||
array_4 = [10, 20, 30]
|
||||
gen = (i + j for i in array_3 for j in array_4)
|
||||
|
||||
array_3 = [4, 5, 6]
|
||||
array_4 = [400, 500, 600]
|
||||
```
|
||||
|
||||
**خروجی:**
|
||||
```py
|
||||
>>> print(list(gen))
|
||||
[401, 501, 601, 402, 502, 602, 403, 503, 603]
|
||||
```
|
||||
|
||||
#### 💡 توضیحات
|
||||
|
||||
- در یک عبارت [تولیدکننده](https://wiki.python.org/moin/Generators)، عبارت بند `in` در هنگام تعریف محاسبه میشه ولی عبارت شرطی در زمان اجرا محاسبه میشه.
|
||||
- پس قبل از زمان اجرا، `array` دوباره با لیست `[2, 8, 22]` مقداردهی میشه و از آنجایی که در مقدار جدید `array`، بین `1`، `8` و `15`، فقط تعداد `8` بزرگتر از `0` است، تولیدکننده فقط مقدار `8` رو برمیگردونه
|
||||
- تفاوت در مقدار `gen_1` و `gen_2` در بخش دوم به خاطر نحوه مقداردهی دوباره `array_1` و `array_2` است.
|
||||
- در مورد اول، متغیر `array_1` به شیء جدید `[1,2,3,4,5]` وصله و از اون جایی که عبارت بند `in` در هنگام تعریف محاسبه میشه، `array_1` داخل تولیدکننده هنوز به شیء قدیمی `[1,2,3,4]` (که هنوز حذف نشده)
|
||||
- در مورد دوم، مقداردهی برشی به `array_2` باعث بهروز شدن شیء قدیمی این متغیر از `[1,2,3,4]` به `[1,2,3,4,5]` میشه و هر دو متغیر `gen_2` و `array_2` به یک شیء اشاره میکنند که حالا بهروز شده.
|
||||
- خیلیخب، حالا طبق منطقی که تا الان گفتیم، نباید مقدار `list(gen)` در قطعهکد سوم، `[11, 21, 31, 12, 22, 32, 13, 23, 33]` باشه؟ (چون `array_3` و `array_4` قراره درست مثل `array_1` رفتار کنن). دلیل این که چرا (فقط) مقادیر `array_4` بهروز شدن، توی [PEP-289](https://www.python.org/dev/peps/pep-0289/#the-details) توضیح داده شده.
|
||||
|
||||
> فقط بیرونیترین عبارت حلقه `for` بلافاصله محاسبه میشه و باقی عبارتها به تعویق انداخته میشن تا زمانی که تولیدکننده اجرا بشه.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### ▶ هر گردی، گردو نیست
|
||||
<!-- Example ID: b26fb1ed-0c7d-4b9c-8c6d-94a58a055c0d --->
|
||||
```py
|
||||
>>> 'something' is not None
|
||||
True
|
||||
>>> 'something' is (not None)
|
||||
False
|
||||
```
|
||||
|
||||
#### 💡 توضیحات
|
||||
- عملگر `is not` یک عملگر باینری واحده و رفتارش متفاوت تر از استفاده `is` و `not` به صورت جداگانهست.
|
||||
- عملگر `is not` مقدار `False` رو برمیگردونه اگر متغیرها در هردو سمت این عملگر به شیء یکسانی اشاره کنند و درغیر این صورت، مقدار `True` برمیگردونه
|
||||
- در مثال بالا، عبارت `(not None)` برابره با مقدار `True` از اونجایی که مقدار `None` در زمینه boolean به `False` تبدیل میشه. پس کل عبارت معادل عبارت `'something' is True` میشه.
|
||||
|
||||
---
|
||||
|
Loading…
x
Reference in New Issue
Block a user