Skip to content

Commit 4d8e193

Browse files
committed
update farsi translation - section 1
1 parent 6592360 commit 4d8e193

File tree

1 file changed

+298
-0
lines changed

1 file changed

+298
-0
lines changed

translations/fa-farsi/section1-temp.md

Lines changed: 298 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,3 +490,301 @@ True
490490
همونطور که مشاهده می‌کنید، ترتیب حذف شدن شیءها باعث تفاوت میشه.
491491

492492
---
493+
494+
495+
### ▶ بی‌نظمی در خود نظم *
496+
<!-- Example ID: 91bff1f8-541d-455a-9de4-6cd8ff00ea66 --->
497+
```py
498+
from collections import OrderedDict
499+
500+
dictionary = dict()
501+
dictionary[1] = 'a'; dictionary[2] = 'b';
502+
503+
ordered_dict = OrderedDict()
504+
ordered_dict[1] = 'a'; ordered_dict[2] = 'b';
505+
506+
another_ordered_dict = OrderedDict()
507+
another_ordered_dict[2] = 'b'; another_ordered_dict[1] = 'a';
508+
509+
class DictWithHash(dict):
510+
"""
511+
یک dict که تابع جادویی __hash__ هم توش پیاده شده.
512+
"""
513+
__hash__ = lambda self: 0
514+
515+
class OrderedDictWithHash(OrderedDict):
516+
"""
517+
یک OrderedDict که تابع جادویی __hash__ هم توش پیاده شده.
518+
"""
519+
__hash__ = lambda self: 0
520+
```
521+
522+
**Output**
523+
```py
524+
>>> dictionary == ordered_dict # اگر مقدار اولی با دومی برابره
525+
True
526+
>>> dictionary == another_ordered_dict # و مقدار اولی با سومی برابره
527+
True
528+
>>> ordered_dict == another_ordered_dict # پس چرا مقدار دومی با سومی برابر نیست؟
529+
False
530+
531+
# ما همه‌مون میدونیم که یک مجموعه فقط شامل عناصر منحصربه‌فرد و غیرتکراریه.
532+
# بیاید یک مجموعه از این دیکشنری‌ها بسازیم ببینیم چه اتفاقی میافته...
533+
534+
>>> len({dictionary, ordered_dict, another_ordered_dict})
535+
Traceback (most recent call last):
536+
File "<stdin>", line 1, in <module>
537+
TypeError: unhashable type: 'dict'
538+
539+
# منطقیه چون dict ها __hash__ توشون پیاده‌سازی نشده. پس بیاید از
540+
# کلاس‌هایی که خودمون درست کردیم استفاده کنیم.
541+
>>> dictionary = DictWithHash()
542+
>>> dictionary[1] = 'a'; dictionary[2] = 'b';
543+
>>> ordered_dict = OrderedDictWithHash()
544+
>>> ordered_dict[1] = 'a'; ordered_dict[2] = 'b';
545+
>>> another_ordered_dict = OrderedDictWithHash()
546+
>>> another_ordered_dict[2] = 'b'; another_ordered_dict[1] = 'a';
547+
>>> len({dictionary, ordered_dict, another_ordered_dict})
548+
1
549+
>>> len({ordered_dict, another_ordered_dict, dictionary}) # ترتیب رو عوض می‌کنیم
550+
2
551+
```
552+
553+
چی شد؟
554+
555+
#### 💡 توضیحات:
556+
557+
- دلیل اینکه این مقایسه بین متغیرهای `dictionary`، `ordered_dict` و `another_ordered_dict` به درستی اجرا نمیشه به خاطر نحوه پیاده‌سازی تابع `__eq__` در کلاس `OrderedDict` هست. طبق [مستندات](https://docs.python.org/3/library/collections.html#ordereddict-objects)
558+
> مقایسه برابری بین شیءهایی از نوع OrderedDict به ترتیب اعضای آن‌ها هم بستگی دارد و به صورت `list(od1.items())==list(od2.items())` پیاده سازی شده است. مقایسه برابری بین شیءهای `OrderedDict` و شیءهای قابل نگاشت دیگر به ترتیب اعضای آن‌ها بستگی ندارد و مقایسه همانند دیکشنری‌های عادی انجام می‌شود.
559+
- این رفتار باعث میشه که بتونیم `OrderedDict` ها رو هرجایی که یک دیکشنری عادی کاربرد داره، جایگزین کنیم و استفاده کنیم.
560+
- خب، حالا چرا تغییر ترتیب روی طول مجموعه‌ای که از دیکشنری‌ها ساختیم، تاثیر گذاشت؟ جوابش همین رفتار مقایسه‌ای غیرانتقالی بین این شیءهاست. از اونجایی که `set` ها مجموعه‌ای از عناصر غیرتکراری و بدون نظم هستند، ترتیبی که عناصر تو این مجموعه‌ها درج میشن نباید مهم باشه. ولی در این مورد، مهم هست. بیاید کمی تجزیه و تحلیلش کنیم.
561+
```py
562+
>>> some_set = set()
563+
>>> some_set.add(dictionary) # این شیء‌ها از قطعه‌کدهای بالا هستند.
564+
>>> ordered_dict in some_set
565+
True
566+
>>> some_set.add(ordered_dict)
567+
>>> len(some_set)
568+
1
569+
>>> another_ordered_dict in some_set
570+
True
571+
>>> some_set.add(another_ordered_dict)
572+
>>> len(some_set)
573+
1
574+
575+
>>> another_set = set()
576+
>>> another_set.add(ordered_dict)
577+
>>> another_ordered_dict in another_set
578+
False
579+
>>> another_set.add(another_ordered_dict)
580+
>>> len(another_set)
581+
2
582+
>>> dictionary in another_set
583+
True
584+
>>> another_set.add(another_ordered_dict)
585+
>>> len(another_set)
586+
2
587+
```
588+
پس بی‌ثباتی تو این رفتار به خاطر اینه که مقدار `another_ordered_dict in another_set` برابر با `False` هست چون `ordered_dict` از قبل داخل `another_set` هست و همونطور که قبلا مشاهده کردید، مقدار `ordered_dict == another_ordered_dict` برابر با `False` هست.
589+
590+
---
591+
592+
593+
### ▶ تلاش کن... *
594+
<!-- Example ID: b4349443-e89f-4d25-a109-82616be9d41a --->
595+
```py
596+
def some_func():
597+
try:
598+
return 'from_try'
599+
finally:
600+
return 'from_finally'
601+
602+
def another_func():
603+
for _ in range(3):
604+
try:
605+
continue
606+
finally:
607+
print("Finally!")
608+
609+
def one_more_func():
610+
try:
611+
for i in range(3):
612+
try:
613+
1 / i
614+
except ZeroDivisionError:
615+
# بذارید اینجا ارور بدیم و بیرون حلقه بهش
616+
# رسیدگی کنیم
617+
raise ZeroDivisionError("A trivial divide by zero error")
618+
finally:
619+
print("Iteration", i)
620+
break
621+
except ZeroDivisionError as e:
622+
print("Zero division error occurred", e)
623+
```
624+
625+
**خروجی:**
626+
627+
```py
628+
>>> some_func()
629+
'from_finally'
630+
631+
>>> another_func()
632+
Finally!
633+
Finally!
634+
Finally!
635+
636+
>>> 1 / 0
637+
Traceback (most recent call last):
638+
File "<stdin>", line 1, in <module>
639+
ZeroDivisionError: division by zero
640+
641+
>>> one_more_func()
642+
Iteration 0
643+
644+
```
645+
646+
#### 💡 Explanation:
647+
648+
- وقتی یک عبارت `return`، `break` یا `continue` داخل بخش `try` از یک عبارت "try...finally" اجرا میشه، بخش `fianlly` هم هنگام خارج شدن اجرا میشه.
649+
- مقدار بازگشتی یک تابع از طریق آخرین عبارت `return` که داخل تابع اجرا میشه، مشخص میشه. از اونجایی که بخش `finally` همیشه اجرا میشه، عبارت `return` که داخل بخش `finally` هست آخرین عبارتیه که اجرا میشه.
650+
- نکته اینجاست که اگه بخش داخل بخش `finally` یک عبارت `return` یا `break` اجرا بشه، `exception` موقتی که ذخیره شده، رها میشه.
651+
652+
---
653+
654+
655+
### ▶ برای چی?
656+
<!-- Example ID: 64a9dccf-5083-4bc9-98aa-8aeecde4f210 --->
657+
```py
658+
some_string = "wtf"
659+
some_dict = {}
660+
for i, some_dict[i] in enumerate(some_string):
661+
i = 10
662+
```
663+
664+
**Output:**
665+
```py
666+
>>> some_dict # یک دیکشنری مرتب‌شده نمایان میشه.
667+
{0: 'w', 1: 't', 2: 'f'}
668+
```
669+
670+
#### 💡 توضیحات:
671+
* یک حلقه `for` در [گرامر پایتون](https://docs.python.org/3/reference/grammar.html) این طور تعریف میشه:
672+
```
673+
for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]
674+
```
675+
به طوری که `exprlist` یک هدف برای مقداردهیه. این یعنی، معادل عبارت `{exprlist} = {next_value}` **برای هر شیء داخل `testlist` اجرا می‌شود**.
676+
یک مثال جالب برای نشون دادن این تعریف:
677+
```py
678+
for i in range(4):
679+
print(i)
680+
i = 10
681+
```
682+
683+
**خروجی:**
684+
```
685+
0
686+
1
687+
2
688+
3
689+
```
690+
691+
آیا انتظار داشتید که حلقه فقط یک بار اجرا بشه؟
692+
693+
**💡 توضیحات:**
694+
695+
- عبارت مقداردهی `i = 10` به خاطر نحوه کار کردن حلقه‌ها، هیچوقت باعث تغییر در تکرار حلقه نمیشه. قبل از شروع هر تکرار، مقدار بعدی که توسط شیء قابل تکرار (که در اینجا `range(4)` است) ارائه میشه، از بسته خارج میشه و به متغیرهای لیست هدف (که در اینجا `i` است) مقداردهی میشه.
696+
697+
* تابع `enumerate(some_string)`، یک متغیر `i` (که یک شمارنده اقزایشی است) و یک حرف از حروف رشته `some_string` رو در هر تکرار برمیگردونه. و بعدش برای کلید `i` (تازه مقداردهی‌شده) در دیکشنری `some_dict`، مقدار اون حرف رو تنظیم می‌کنه. بازشده این حلقه می‌تونه مانند مثال زیر ساده بشه:
698+
```py
699+
>>> i, some_dict[i] = (0, 'w')
700+
>>> i, some_dict[i] = (1, 't')
701+
>>> i, some_dict[i] = (2, 'f')
702+
>>> some_dict
703+
```
704+
705+
---
706+
707+
### ▶ اختلاف زمانی در محاسبه
708+
<!-- Example ID: 6aa11a4b-4cf1-467a-b43a-810731517e98 --->
709+
1\.
710+
```py
711+
array = [1, 8, 15]
712+
# یک عبارت تولیدکننده عادی
713+
gen = (x for x in array if array.count(x) > 0)
714+
array = [2, 8, 22]
715+
```
716+
717+
**خروجی:**
718+
719+
```py
720+
>>> print(list(gen)) # پس بقیه مقدارها کجا رفتن؟
721+
[8]
722+
```
723+
724+
2\.
725+
726+
```py
727+
array_1 = [1,2,3,4]
728+
gen_1 = (x for x in array_1)
729+
array_1 = [1,2,3,4,5]
730+
731+
array_2 = [1,2,3,4]
732+
gen_2 = (x for x in array_2)
733+
array_2[:] = [1,2,3,4,5]
734+
```
735+
736+
**خروجی:**
737+
```py
738+
>>> print(list(gen_1))
739+
[1, 2, 3, 4]
740+
741+
>>> print(list(gen_2))
742+
[1, 2, 3, 4, 5]
743+
```
744+
745+
3\.
746+
747+
```py
748+
array_3 = [1, 2, 3]
749+
array_4 = [10, 20, 30]
750+
gen = (i + j for i in array_3 for j in array_4)
751+
752+
array_3 = [4, 5, 6]
753+
array_4 = [400, 500, 600]
754+
```
755+
756+
**خروجی:**
757+
```py
758+
>>> print(list(gen))
759+
[401, 501, 601, 402, 502, 602, 403, 503, 603]
760+
```
761+
762+
#### 💡 توضیحات
763+
764+
- در یک عبارت [تولیدکننده](https://wiki.python.org/moin/Generators)، عبارت بند `in` در هنگام تعریف محاسبه میشه ولی عبارت شرطی در زمان اجرا محاسبه میشه.
765+
- پس قبل از زمان اجرا، `array` دوباره با لیست `[2, 8, 22]` مقداردهی میشه و از آن‌جایی که در مقدار جدید `array`، بین `1`، `8` و `15`، فقط تعداد `8` بزرگتر از `0` است، تولیدکننده فقط مقدار `8` رو برمیگردونه
766+
- تفاوت در مقدار `gen_1` و `gen_2` در بخش دوم به خاطر نحوه مقداردهی دوباره `array_1` و `array_2` است.
767+
- در مورد اول، متغیر `array_1` به شیء جدید `[1,2,3,4,5]` وصله و از اون جایی که عبارت بند `in` در هنگام تعریف محاسبه میشه، `array_1` داخل تولیدکننده هنوز به شیء قدیمی `[1,2,3,4]` (که هنوز حذف نشده)
768+
- در مورد دوم، مقداردهی برشی به `array_2` باعث به‌روز شدن شیء قدیمی این متغیر از `[1,2,3,4]` به `[1,2,3,4,5]` میشه و هر دو متغیر `gen_2` و `array_2` به یک شیء اشاره میکنند که حالا به‌روز شده.
769+
- خیلی‌خب، حالا طبق منطقی که تا الان گفتیم، نباید مقدار `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) توضیح داده شده.
770+
771+
> فقط بیرونی‌ترین عبارت حلقه `for` بلافاصله محاسبه میشه و باقی عبارت‌ها به تعویق انداخته میشن تا زمانی که تولیدکننده اجرا بشه.
772+
773+
---
774+
775+
776+
### ▶ هر گردی، گردو نیست
777+
<!-- Example ID: b26fb1ed-0c7d-4b9c-8c6d-94a58a055c0d --->
778+
```py
779+
>>> 'something' is not None
780+
True
781+
>>> 'something' is (not None)
782+
False
783+
```
784+
785+
#### 💡 توضیحات
786+
- عملگر `is not` یک عملگر باینری واحده و رفتارش متفاوت تر از استفاده `is` و `not` به صورت جداگانه‌ست.
787+
- عملگر `is not` مقدار `False` رو برمیگردونه اگر متغیرها در هردو سمت این عملگر به شیء یکسانی اشاره کنند و درغیر این صورت، مقدار `True` برمیگردونه
788+
- در مثال بالا، عبارت `(not None)` برابره با مقدار `True` از اونجایی که مقدار `None` در زمینه boolean به `False` تبدیل میشه. پس کل عبارت معادل عبارت `'something' is True` میشه.
789+
790+
---

0 commit comments

Comments
 (0)