| کانال توسعه‌دهندگان پایتون |
6.62K subscribers
38 photos
2 videos
4 files
43 links
⭕️ کانال توسعه‌دهندگان پایتون دولوپیکس

💠 دولوپیکس | جامعه توسعه‌دهندگان ایرانی

💎 @Developix
🚀 Developix.ir

📌 پشتیبانی و تبلیغات:
@DevelopixSupport
Download Telegram
Adaptive Machine Learning Algorithms with Python.pdf
9.4 MB
📥 دانلود کتاب

📚 Adaptive Machine Learning Algorithms with Python: Solve Data Analytics and Machine Learning Problems on Edge Devices

💎 Channel: @DevelopixPython
💠 عملگرها دستوراتی هستند که بر روی داده‌ها اعمال می‌شود و نتیجه جدیدی تولید می‌کند. بسته به نوع عملگر، ممکن است برای انجام یک عملیات ساده مانند جمع یا ضرب دو عدد، یا برای اعمال منطقی به داده‌ها مانند مقایسه دو عدد یا چک کردن وجود یک عنصر در یک لیست، استفاده شود. در کل، عملگرها یکی از اصلی‌ترین اجزای زبان های برنامه‌نویسی هستند و بدون آنها نمی‌توان عملیات‌های مورد نیاز را انجام داد.

🌀 در ادامه به معرفی انوع عملگرها و کاربرد آن‌ها میپردازیم.

#Operators
#عملگر

✍🏻 *ژنرال*

💎 Channel: @DevelopixPython
| کانال توسعه‌دهندگان پایتون |
💠 عملگرها دستوراتی هستند که بر روی داده‌ها اعمال می‌شود و نتیجه جدیدی تولید می‌کند. بسته به نوع عملگر، ممکن است برای انجام یک عملیات ساده مانند جمع یا ضرب دو عدد، یا برای اعمال منطقی به داده‌ها مانند مقایسه دو عدد یا چک کردن وجود یک عنصر در یک لیست، استفاده…
🔘 عملگرهای ریاضی
🔰 این عملگرها برای انجام عملیات ریاضی از جمله جمع، تفریق، ضرب و تقسیم بر روی اعداد استفاده می‌شوند. علاوه بر این، پایتون از عملگرهای دیگری مانند توان، تقسیم صحیح، باقی‌مانده و ... نیز پشتیبانی می‌کند. این عملگرها از اهمیت ویژه‌ای برخوردارند و با ترکیب آنها با هم می‌توان عملیات‌های پیچیده‌تری را انجام داد.

⚙️ مثال:
a = 2 + 3 # a = 5
b = 4 - 1 # b = 3
c = 5 * 2 # c = 10
d = 7 / 2 # d = 3.5
e = 8 % 3 # e = 2
f = 7 // 2 # f = 3
g = 2 ** 3 # g = 8

🔘 عملگرهای مقایسه‌ای
🔰 مقایسه‌گرها به کاربر این امکان را می‌دهند تا دو مقدار را با یکدیگر مقایسه کنند. به این صورت که این عملگرها مقادیر را با‌هم مقایسه کرده و نتیجه آن را به صورت True یا False برمی‌گردانند.

⚙️ مثال:
a = 5 == 5 # a = True
b = 6 != 6 # b = False
c = 8 > 10 # c = False
d = 4 < 6 # d = True
e = 9 >= 10 # e = False
f = 3 <= 3 # f = True

🔘 عملگرهای منطقی
🔰 این نوع از عملگرها که شامل and ، or و not هستند برای ایجاد شرایط منطقی و بررسی آن‌ها در برنامه‌های پایتون استفاده می‌شوند. این عملگرها برای مقایسه و بررسی درستی یا نادرستی بیان‌ها و شرایط استفاده می‌شوند و به دلیل استفاده در منطق ریاضی به آنها عملگرهای منطقی گفته می‌شود و بسیار حائز اهمیت هستند.

⚙️ مثال:
a = True and False # a = False
b = True or False # b = True
c = not True # c = False

🔘 عملگرهای بیتی
🔰 عملگرهای بیتی در پایتون برای کار با بیت‌های دودویی( باینری «0 و 1» ) به کار می‌روند و به کاربران اجازه می‌دهند تا بر روی بیت‌ها عملیات منطقی مانند AND، OR، XOR و NOT را انجام دهند و از طریق کار با داده‌های دودویی سرعت و بهینه بودن کد را افزایش دهند.

⚙️ مثال:
a = 4 & 5 # a = 4
b = 4 | 5 # b = 5
c = 4 ^ 5 # c = 1
d = ~4 # d = -5
e = 4 << 2 # e = 16
f = 4 >> 1 # f = 2

🔘 عملگر های اختصاصی
🔰 این عملگرها در پایتون برای اختصاص دادن مقدار به یک متغیر با استفاده از عملگرهای ریاضی، منطقی و بیتی استفاده می‌شوند. برای مثال، اگر متغیر a را داشته باشیم و بخواهیم مقدار آن را با یک عدد دیگر جمع کنیم و حاصل را به خودش بازگردانیم، می‌توانیم از عملگر += استفاده کنیم.

⚙️ مثال:
a = 1 # a = 1
b := 2 # (b := 2)
c += 3 # c = c + 3
d -= 4 # d = d - 4
e *= 5 # e = e * 5
f /= 6 # f = f / 6
g //= 7 # g = g // 7
h %= 8 # h = h % 8
i **= 9 # i = i ** 9

🔘 عملگر های ویژه
🔰 عملگرهای ویژه در پایتون عملگرهایی هستند که نحوه‌ی عملکرد آن‌ها با سایر عملگرهای ریاضی و منطقی متفاوت است و برای کاربردهای خاصی طراحی شده‌اند. برای مثال، عملگر is برای بررسی همانی دو متغیر و عملگر in برای بررسی وجود یک مقدار در یک لیست یا رشته استفاده می‌شوند.

⚙️ مثال:
a = "hello"
b = "world"

c = a is b # c = False
d = a is not b # d = True

e = "l" in "hello" # e = True
f = "c" not in "world" # f = True


#Operators
#عملگر

✍🏻 *ژنرال*

💎 Channel: @DevelopixPython
💠 متدهای خاص در کلاس ها

🔸 در پایتون، Magic methodها یا همان Dunder methodها متدهای خاصی هستند که با استفاده از نام‌های خاصی که با _‌_ شروع و به‌‌پایان می‌رسند، به کلاس‌ها رفتارهای پیش فرضی می‌دهند. این نوع متدها به شما این امکان را می‌دهند که کلاس‌های خود را بهتر و با عملکرد بالاتر بنویسید.

🔹 داندرمتدها می‌توانند برای پیاده‌سازی اعمال ریاضی، مقایسه، شیوه ترکیب و تعریف عملکردهای دیگر برای کلاس‌ها استفاده شوند. برای مثال با تعریف متد __add__ می‌توانیم عمل جمع را برای دو شیء در کلاس تعریف شده، به صورت خودکار انجام دهیم. همچنین با تعریف متد __str__ می‌توانیم رشته‌ای را که نشان دهنده نحوه نمایش یک شیء است، تعریف کنیم.

🔸 در کل، Magic method ها در پایتون به کاربران اجازه می‌دهند که رفتار و عملکرد کلاس‌های خود را به شکلی سفارشی و مشخصی تعریف کنند و این باعث افزایش انعطاف پذیری و خوانایی کد می‌شود.

🌀 در ادامه، به معرفی بخش به بخش این نوع از متدها خواهیم پردازیم.

#MagicMethod #DunderMethod #Operator
#داندرمتدها #عملگرها


✍🏻 *ژنرال*

💎 Channel: @DevelopixPython
💠 داندرمتد ها
💠 بخش اول
(موارد مرتبط با عملگرهای ریاضی و مقایسه)

🌀 برای درک بهتر موارد مرتبط با این قسمت، پیشنهاد می‌شود پست مربوط به عملگرها را مطالعه کنید.

🔰 از magic methodهای مرتبط با عملگرهای ریاضی در پایتون برای تعریف عملگرهای ریاضی برای کلاس‌های سفارشی استفاده می‌شود.

🔸 به عنوان مثال، شما می‌توانید با تعریف متد __add__ برای یک کلاس، عملگر جمع + را برای اشیاء این کلاس تعریف کنید. به همین ترتیب، با تعریف دیگر متدهای مربوط به سایر عملگرهای ریاضی، می‌توانید رفتار خاصی را برای این عملگرها در کلاس‌های خود تعریف کنید.

🔸 در کل، استفاده از این magic methodها به شما امکان می‌دهد که به کلاس خود عملکردی مشابه کلاس‌های دیگر در پایتون بدهید و با تعریف رفتارهای خاص برای عملگرهای ریاضی، این عملکرد را بهبود بخشید.

🔹 داندرمتدهای مرتبط به این بخش عبارتند از:
1. __add__(self, other) : +
2. __sub__(self, other) : -
3. __truediv__(self, other) : /
4. __mul__(self, other) : *
5. __floordiv__(self, other) : //
6. __mod__(self, other) : %
7. __pow__(self, other) : **

🔘 برای مثال، میدانیم که در یک رشته، عملگر "-" به‌صورت استاندارد پشتیبانی نمی‌شود زیرا تعریف نشده است. با این حال، با ارث‌بری از کلاس str و اضافه کردن این متد به آن می‌توانیم از آن استفاده کنیم. برای ورودی های غیرقابل‌قبول هم ارورهایی درنظر می‌گیریم. یعنی:

class Str(str):
def __sub__(self, __value: str) -> str:
if not isinstance(__value, str):
raise TypeError(f"value must be str, not {type(__value).__name__}")

elif self.endswith(__value):
return self.removesuffix(__value)

else:
raise ValueError(f'"{self}" does not end with "{__value}"')

Str("DevelopixPython") - "Python" # "Developix"


🔰 از داندرمتدهای مرتبط با عملگرهای مقایسه‌ در پایتون برای تعریف رفتار خاصی برای عملگرهای مقایسه‌ای مانند >, <, >=, <=, == و != استفاده می‌شود. با تعریف این متدها، می‌توانید رفتار خاصی را برای مقایسه دو شیء با هم تعریف کنید و در نتیجه از این مقایسه ها به شکلی خاصی استفاده کنید.

🔸 به عنوان مثال، شما می‌توانید با تعریف متد __eq__ دو شیء را برای برابری باهم مقایسه کنید. همچنین، با تعریف دیگر متدها مانند __gt__ و __lt__، می‌توانید دو شیء را برای مقایسه بزرگتری یا کوچکتری با هم مقایسه کنید.

🔸 در کل، استفاده از magic method های مرتبط با عملگرهای مقایسه در پایتون به شما امکان می‌دهد که رفتار خاصی برای مقایسه دو شیء با هم تعریف کنید.

🔹 داندرمتدهای مرتبط به این بخش عبارتند از:
1. __lt__(self, other) : <
2. __le__(self, other) : <=
3. __gt__(self, other) : >
4. __ge__(self, other) : >=
5. __eq__(self, other) : ==
6. __ne__(self, other) : !=

🔘 فرض کنید می‌خواهید دو مقدار را که تنها در نوع داده‌ با هم تفاوت دارند با یکدیگر مقایسه کنید (برای مثال 123 و "123"). در حالت معمول، اگر از عملگر "==" برای مقایسه این دو داده استفاده کنید، مقدار False برگردانده می‌شود. با این حال، می‌توانیم این متد را override کنیم تا اگر ورودی یک عدد صحیح و مقدار آن‌ها برابر بود، اول داده را تبدیل به str کرده و بعد آن را به متد والد بدهد.
یعنی:
class Str(str):
def __eq__(self, __value: object) -> bool:
if isinstance(__value, int):
return super().__eq__(__value.__str__())

return super().__eq__(__value)

Str("123") == 123 # True

#MagicMethod #DunderMethod #Operator
#داندرمتدها #عملگرها

✍🏻 *ژنرال*

💎 Channel: @DevelopixPython
💠 داندرمتد ها
💠 بخش دوم
(موارد مرتبط با عملگرهای تخصیص و بیتی)

🌀 برای درک بهتر موارد مرتبط با این قسمت، پیشنهاد می‌شود پست مربوط به عملگرها را مطالعه کنید.

🔰 از magic methodهای مرتبط با عملگرهای بیتی در پایتون برای تعریف رفتاری خاص برای عملگرهای بیتی مانند &، | و ... استفاده می‌شود.

🔸 با استفاده از این داندرمتدها، می‌توانید عملگرهای مرتبط را به شکلی سفارشی شده در کلاس خود استفاده کنید. این قابلیت به شما کمک می‌کند تا در برنامه‌های پایتونی که با داده‌های بیتی سروکار دارند، عملگرهای بیتی را با رفتار خاصی تعریف کنید.

🔹 داندرمتدهای مرتبط به این بخش عبارتند از:
1. __and__(self, other) : &
2. __or__(self, other) : |
3. __invert__(self) : ~
4. __xor__(self, other) : ^
5. __rshift__(self, other) : >>
6. __lshift__(self, other) : <<

🔘 فرض کنید قصد دارید دو رشته را با یکدیگر مقایسه کنید و تمامی حروف مشترک آنها را به صورت یک رشته خروجی دهید، به طوری که عملکرد آن مشابه عملکرد استاندارد برای اشتراک در set و dict باشد. در این صورت، شما می‌توانید برای عملگر "&"، متد مربوطه را تعریف کنید که با فراخوانی آن، تمامی حروف مشترک بین دو رشته(یا Iterable) ورودی را درقالب str برگردانید. یعنی:

class Str(str):
def __and__(self, __value: object) -> str:
if isinstance(__value, (Iterable, str)):
return "".join(
letter
for letter in self
if letter in __value
)

raise TypeError(
f"value must be Iterable or str, not {type(__value).__name__}")

Str("Developix") & "Dpx" # "Dpx"

🔰 عملگرهای تخصیص مانند +=، -=، *= و ...، برای انجام عملیات‌های ریاضی، بیتی و ... بر روی یک متغیر استفاده می‌شوند.

🔸 این داندرمتدها، هنگامی که از عملگرهای تخصیص استفاده می‌شود، به صورت خودکار فراخوانی می‌شوند و نتیجه عملیات را در همان شیء ذخیره می‌کنند. به عنوان مثال، اگر a یک شیء از یک کلاس باشد، عملگر += با استفاده از متد __iadd__، مقدار a را با یک مقدار دیگر جمع کرده و نتیجه را در همان a ذخیره می‌کند.

🔹 داندرمتدهای مرتبط به این بخش عبارتند از:
1. __iadd__(self, other) : +=
2. __isub__(self, other) : -=
3. __itruediv__(self, other) : /=
4. __imul__(self, other) : *=
5. __ifloordiv__(self, other) : //=
6. __imod__(self, other) : %=
7. __ipow__(self, other) : **=
8. __iand__(self, other) : &=
9. __ior__(self, other) : |=
10. __ixor__(self, other) : ^=
11. __irshift__(self, other) : >>=
12. __ilshift__(self, other) : <<=
13. __radd__(self, other) : +=
14. __rmul__(self, other) : *=
15. __rfloordiv__(self, other) : //=
16. __rmod__(self, other) : %=
17. __rpow__(self, other) : **=
18. __rand__(self, other) : &=
19. __ror__(self, other) : |=
20. __rxor__(self, other) : ^=
21. __rrshift__(self, other) : >>=
22. __rlshift__(self, other) : <<=
23. __rsub__(self, other) : -=
24. __rtruediv__(self, other) : /=

🔘 بر اساس مثالی که برای عملگر "-" ارائه دادیم، می‌توانیم کد مشابهی برای عملگر "-=" نوشته و از آن استفاده کنیم. در اینجا، فقط با یک تغییر، در صورتی که ورودی نوع int باشد، ابتدا آن را به str تبدیل می‌کنیم و سپس بررسی می‌کنیم که آیا این رشته با ورودی به پایان می‌رسد یا خیر. یعنی:

class Str(str):
def __isub__(self, __value: object) -> bool:
if isinstance(__value, str):
return self.__sub__(__value)

if isinstance(__value, int):
__value = __value.__str__()

elif not isinstance(__value, str):
raise TypeError(f"value must be str, not {type(__value).__name__}")

if self.endswith(__value):
return self.removesuffix(__value)

raise ValueError(f'"{self}" does not end with "{__value}"')

var = Str("123")
var -= 3 # var = "12"

#MagicMethod #DunderMethod #Operator
#داندرمتدها #عملگرها

✍🏻 *ژنرال*

💎 Channel: @DevelopixPython
درود.
تست نویسی یکی از مهم ترین ارکان توسعه نرم افزار هست. چهار تا اصطلاح معروف که موقع تست نویسی به کار میره:

1. False-Negative
کد شما مشکل "داره" + تست داره به غلط میگه که کد شما مشکلی نداره.

2. False-Positive
کد شما مشکلی "نداره" + تست داره به غلط میگه که کد شما مشکل داره.

3. True-Negative
کد مشکلی "نداره" + تست داره به درستی نشون میده که مشکلی نداره.

4. True-Positive
کد مشکل "داره" + تست به درستی نشون میده که مشکل داره .

خیلی از افراد تعاریف دیگری از این ها دارن که کاملا برعکس چیزیه که خوندین. ولی این تعاریف منبعش از کتاب xUnit Test Patterns از آقای Gerard Meszaros که آقای Martin Fowler هم تاییدش کردن.

راه درست فکر کردن بهش هم این هست که به جای "مشکل" یا "باگ" بیاید از "کرونا" استفاده کنید. وقتی تست کرونا میدید و کرونا دارید(باگ دارید) توی تست میزنه POSITIVE. ولی اگه کرونا داشتید و تو تست زد NEGATIVE یعنی یک NEGATIVE عه غلط هست یا همون false negative.

👤 SorousH

💎 Channel: @DevelopixPython
💠 داندرمتد ها
💠 بخش سوم
(Descriptor)

🔰 به طور کلی Descriptorها به شما اجازه می‌دهند تا رفتارهای خاصی را برای متغیرهای یک آبجکت تعریف کنید. این رفتارها ممکن است شامل تعیین، بازیابی، تغییر و حذف مقادیر متغیرهای آن باشند.

🔸 برای تعریف این رفتارها، شما به magic methodهایی نیاز دارید که برای هر نوع descriptor می‌تواند متفاوت باشند. به عنوان مثال، اگر شما به دنبال ایجاد یک descriptor با قابلیت خواندن و نوشتن هستید، باید از __get__ و __set__ استفاده کنید.

🔹 داندرمتدهای مرتبط به این بخش عبارتند از:
1. __get__(self, instance, owner)
2. __set__(self, instance, value)
3. __delete__(self, instance)

🔘 دو کلاس به نام های Python و Developix تعریف می‌کنیم. در کلاس Python، اتریبیوتی به نام group_name تعریف شده است که مقدار اولیه آن برابر با نام کلاس است. وقتی از داندرمتد __get__ استفاده می‌شود، با استفاده از group_name، لینک گروه برگردانده می‌شود و در داندرمتد __set__ با استفاده از value، مقدار group_name تغییر می‌کند.

class Python:
def __init__(self):
self.group_name = self.__class__.__name__

def __get__(self, object_instance, owner_class=None):
return object_instance.gp_link_form.format(self.group_name)

def __set__(self, object_instance, value):
self.group_name = value

class Developix:
Python = Python()

def __init__(self):
self.gp_link_form = "https://t.me/IR{0}GP"

Developix = Developix()
print(Developix.Python) # https://t.me/IRPythonGP

Developix.Python = "PythonNewName"
print(Developix.Python) # https://t.me/IRPythonNewNameGP

#MagicMethod #DunderMethod #Operator
#داندرمتدها #عملگرها

✍🏻 *ژنرال*

💎 Channel: @DevelopixPython
💠 اصل جانشینی لیسکف
💠 Liskov Substitution Principle (LSP)

خانم Barbara Liskov در سال ۱۹۸۷ یه اصلی رو به نام LSP معرفی کردن که یکی از اصول طراحی کلاس ها در Object Oriented Programming هست.

به طور خلاصه این اصل میگه اگر تایپ B از تایپ A ارث بری میکنه، هرجایی که ما نمونه‌ای از تایپ A داشته باشیم باید بتونیم به‌جاش نمونه‌ای از تایپ B رو قرار بدیم بدون اینکه برنامه به مشکل بخوره. در غیر این‌صورت این رابطه ارث بری صحیح نیست.

مثال: فرض کنید یه کلاس base داریم به اسم Bird که یک متد داره به اسم Fly:

class Bird:
def fly(self):
print("I can fly...")

و دو تا subclass داریم به اسم Duck (اردک) و Ostrich (شترمرغ) که از Bird ارث بری میکنن:

class Duck(Bird):
pass

class Ostrich(Bird):
pass

الان اردک میتونه پرواز کنه چون یه پرنده هست، ولی آیا شترمرغ میتونه پرواز کنه؟ نه نمیتونه. آیا پرنده نیست؟ چرا هست. پس این رابطه درست نیست و اصل LSP رو رعایت نمیکنه.

رابطه ی صحیح چطور میتونه باشه؟ اینکه تشخیص بدیم اصلا Fly متد درستی برای Bird نبوده و اون رو به این شکل بازنویسی کنیم:

class Bird:
pass

class FlyingBirds(Bird):
def fly(self):
print("I can fly...")

class Duck(FlyingBirds):
pass

class Ostrich(Bird):
pass

👤 SorousH

💎 Channel: @DevelopixPython
#سوال
خروجی کد زیر چیست ⁉️

✍️ *ژنرال*

💎 Channel: @DevelopixPython
Please open Telegram to view this post
VIEW IN TELEGRAM
#سوال
خروجی کد بالا چیست ⁉️

✍️ *ژنرال*

💎 Channel: @DevelopixPython
Please open Telegram to view this post
VIEW IN TELEGRAM
💠 ماژول OS

🔺 این ماژول کاربردی برای تعامل با سیستم‌عامل به طور پیش‌فرض روی نسخه های پایتونی وجود داره. در ادامه متدهای کاربردی اون رو بررسی می کنیم.

🔻 os.name -> str
🔘 تشخیص نوع سیستم عامل:
os.name # "nt" # windows
os.name # "posix" # linux or MacOS


🔻 os.getcwd() -> str
🔘 دریافت مسیر فعلی.


🔻os.rename(path, newPath)
🔘 تغییر اسم فایل و دایرکتوری:
os.rename("Path/OldName.md", "Path/NewName.md")
os.rename("Path", "NewPath")


🔻 os.access(path, mode) -> bool
🔘 بررسی سطح دسترسی به یک فایل:
Modes :
— F_OK # find
— R_OK # readable
— W_OK # writable
— X_OK # executable

os.access("idk/os.py", os.R_OK) # True



🔻os.listdir(path) -> list
🔘 دریافت لیست فایل و دایرکتوری ها در مسیر مشخص شده.
🔘 در صورتی که مقداری قرار ندید مسیر فعلی رو در نظر می گیره.
os.listdir(
) # ["file_x", "dir_y"]


🔻os.mkdir(path)
🔘 ایجاد دایرکتوری:
os.mkdir("DPX")
os.listdir() #
["file_x", "dir_y", "DPX"]



🔻os.chdir(path)
🔘 تغییر مسیر فعلی:
os.getcwd() # "Path"

os.chdir("NewPath")
os.getcwd() # "NewPath"



🔻os.environ -> dict
🔘 دریافت متغییر های محیطی سیستم عامل.



🔻os.getlogin() -> str
🔘 دریافت نام کاربری که به سیستم لاگین کرده.
os.getlogin() # "coder"



🔻os.walk(path) => generator
🔘 دریافت محتوای یک دایرکتوری و ساب دایرکتوری ها.
os.walk("Path") # [ (address, [folders], [files]) ]


🔻os.makedirs(path)
این متد مثل متد mkdir برای ایجاد فایل مورد استفاده قرار می گیره. ولی تفاوتی که با متد قبلی داره اینه که در متد قبلی وقتی داخل یک دایرکتوری یک دایرکتوری ایجاد می کنیم، باید دایرکتوری اولی وجود داشته باشه تا دایرکتوری دوم ایجاد بشه ولی تو makedirs این مشکل وجود نداره.
os.listdir() # ["file_x", "dir_y"]

os.mkdir("D1/D2/D3")
# Error : FileNotFoundError

os.makedirs("D1/D2/D3")



🔻os.remove(path)
🔘 حذف فایل.

🔻os.rmdir(path)
🔘 حذف دایرکتوری هایی که محتوایی در آن قرار ندارد.

🔻os.system(command)
🔘 اجرا دستورات سیستمی.


💠 منبع :
◽️ https://docs.python.org/3/library/os.html

👤 ȺʍìɾⱮօհąʍʍąժ

💎 Channel: @DevelopixPython
💠 ماژول Shutil

🔺 این ماژول برای کار با فایل مورد استفاده قرار می گیره. در ادامه به بررسی متدهای این ماژول می پردازیم.

🔻shutil.copyfile(path, newPath)
🔘 برای کپی فایل
shutil.copyfile("File.txt", "Dir/NewFile.txt")


🔻 shutil.copy(path, newPath)
🔘 این متد عملکرد متد copyfile داره ولی امکان تغییر اسم فایل وجود نداره و فقط کافیه اسم دایرکتوری مورد نظر بنویسید.
shutil.copy("File.txt", "Dir") # copy file "Dir\File.txt"



🔻shutil.copy2(path, newPath)
🔘 این متد دقیقا عملکرد متد copy داره ولی تفاوتی که وجود داره اینه که متادیتا های فایل رو هم انتقال میده.



🔻shutil.copytree(path, newPath)
🔘 کپی تمام محتوای یک دایرکتوری، نکته‌ایی که وجود داره اینه که باید مقداری که به جای newPath قرار میدید آدرس یک دایرکتوری که از قبل وجود نداره باشه.


🔻shutil.rmtree(path)
🔘 برای حذف دایرکتوری به همراه تمام محتوای موجود در اون استفاده میشه.


🔻shutil.move(path, newPath)
🔘 انتقال فایل.

💠 منبع :
◽️ https://docs.python.org/3/library/shutil.html

👤 ȺʍìɾⱮօհąʍʍąժ

💎 Channel: @DevelopixPython
💢 معرفی میکرو فریمورک‌ فلسک

یکی از دلایل محبوبیت زبان پایتون، داشتن ابزار و فریمورک‌های متعدد و قدرتمند است که کار و عملکرد این زبان را چند برابر و کار توسعه‌دهنده را آسان و سریع‌تر می‌کنند.

یکی از بهترین‌ میکرو فریمورک‌های پایتون برای کار در حوزه وب میکرو فریمورک Flask است که توسط Armin Ronacher با زبان Python طراحی و نوشته شده است و از سال 2010 تحت لایسنس BSD در انتشار عموم قرار گرفته است.

از آنجایی به فلسک یک میکرو فریمورک گفته می‌شود که ساده است و بسیاری از ابزار‌ها و ویژگی‌های رایج فریمورک‌ها را به طور پیش‌فرض ندارد برای مثال فلسک هیچ لایه انتزاعی پایگاه داده و همچنین ابزار و ویژگی‌ای برای اعتبارسنجی فرم‌ها به طور پیش‌فرض ندارد همین امر باعث سادگی آن شده است و برنامه‌نویس درگیر مسائل پیچیده و اضافه نمی‌شود.

با وجود سادگی، Flask قدرت زیادی دارد و شرکت‌های بزرگی مانند LinkedIn، Netflix و Reddit از آن استفاده کرده‌اند.

ویژگی‌های Flask به طور خلاصه عبارتند از:

- استفاده از الگوی Jinja
- مستندات ساده و جامع
- سازگاری با WSGI
- امکان ساخت کوکی‌هایی با امنیت بالا

با استفاده از این ابزارها، توسعه دهندگان قادر خواهند بود فرآیند توسعه برنامه را بهبود بخشیده و با سرعت و سهولت بیشتری پیش بروند.

👤 Maryam

💎 Channel: @DevelopixPython
HashMaps به بیان ساده:
قرار هست ببینیم associative array چیه، hashmap چیه، چه ارتباطی به dictionary داره، ویژگی هاشون چیه، hash collision چیه، چطور برطرف میشن، نمونه خیلی سادش رو پیاده سازی کنیم و در انتها یه نمونه کامل هم ببینیم ازش.

خب... زمانی که ما یک سری دیتا داریم که به هم مرتبط هستن میتونیم اون ها رو توی یه collection نگهداری کنیم مثلا array. اطلاعاتی مثل تمام نمرات دانش آموزان یک کلاس:
grades = [17, 19, 18, ...]
و با ایندکس های عددی بهشون دسترسی پیدا کنیم:
grades[2]
خیلی هم سریع هستن array ها تو دسترسی چون مستقیم میریم سراغ همون نمره ای که نیاز داریم.
مشکل کجاست؟
مشکل اینه که برای ما سخته حفظ کنیم کدوم ایندکس برای کدوم شخص بوده و ترجیح میدیم که اگه نمره ی شخصی رو میخوایم به جای اینکه یه عدد بی معنی بدیم، اسمش رو بدیم و نمرش رو بگیریم:
grades["ali"]
راه حل چیه؟
اینکه اسمش رو(که بهش میگیم کلید) متصل یا مربوط یا "associate" بکنیم به نمرش.
چطوری؟ مثلا:
grades = [("reza", 17), ("sara", 19), ("ali", 18)]
و بعد هم اینجوری میگیریم:
def get_grade(person_name):
for name, grade in grades:
if name == person_name:
return grade

print(get_grade("ali"))
خیلی بهتر و راحت تر شد الان...
چیزی که ما بالا ساختیم یک پیاده سازی (بد) از associative array بود. چون associate کردیم یک کلید رو به مقدارش. associative array یک abstract هست و میتونه به شکل های مختلف پیاده سازی بشه.

خب... فقط یه مشکلی هست الان:
قبلا که با ایندکس میگرفتیم صاف میرفتیم سراغ خودش، الان مجبوریم که iterate کنیم روشون و دونه دونه بگردیم تا برسیم به اونی که میخوایم. کنده!! (شما مثال های این پست رو با ۱۰۰۰ تا داده مثلا تصور کنید)

راه حل چیه؟
اینکه بیایم "یه جوری" این اسم ها رو map کنیم به ایندکس های عددی تا دوباره بتونیم صاف بریم سراغ اونی که میخوایم و سرعت بهتر بگیریم.

چطور اینکارو بکنیم؟
مثلا بیایم یک فانکشن بنویسیم که از کلیدها عدد تولید کنیم به این صورت که اعداد اسکی متناظر با هر حرف از کلیدمون رو باهم جمع کنیم. یعنی برای sara داریم:
s: 115
a: 97
r: 114
در نتیجه:
"sara" # -> 115 + 97 + 114 + 97 -> 423
این میشه فانکشنش:
def hash_func(string):
return sum(map(ord, string))
حالا یه لیست بسازیم که ۵ تا جای خالی داره:
grades = [None, None, None, None, None]

خب حالا الان عددی که از هش کردن(پس یه هش فانکشن ساده بود اون) کلید sara به دست آوردیم و چطور map کنیم به یکی از ایندکس های لیستمون؟ ما که ۴۲۳ تا slot نداریم...
باقی ماندش رو با طول لیستمون حساب کنیم!
اینطوری مطمئن هستیم که داخل اون رنجی که میخوایم هست. پس:
423 % 5 -> 3
کافیه sara و نمرش رو توی ایندکس شماره ۳ ذخیره کنیم:
grades = [None, None, None, ("sara", 19), None]
اگه همین کار رو برای باقی هم بکنیم همچین چیزی میشه:
grades = [
("ali", 18),
None,
None,
("sara", 19),
("reza", 17),
]
(تو پرانتز حواسمون هست که ترتیبش عوض شد...)

الان خوب شد. هر کدوم از نمره هارو بخوایم بگیریم اول اون کلید رو hash میکنیم بعد باقی ماندش رو حساب میکنیم میشه ایندکس مورد نظر. دیگه iteration ای در کار نیست و به time complexity عه O(1) رسیدیم. الان get_grade عه ما اینطوری شد:

def hash_func(string):
return sum(map(ord, string))

def get_grade(person_name):
hash_value = hash_func(person_name)
idx = hash_value % 5
return grades[idx][1]

print(get_grade("reza"))

موقع insert کردن هم دقیقا برعکس همین شکل عمل میکنیم یعنی ابتدا هش میکنیم بعد باقیمانده میگیریم بعد که فهمیدیم کدوم slot برای اون کلید میشه میذاریمش اونجا. درواقع هر چیزی که برای get کردن میگیم برعکسش برای set کردن میشه.

خب ما الان تونستیم associative array رو با کمک hashmap پیاده سازی کنیم :) بریم ادامش...

حالا اگه اسم یکی دیگه از دانشجو ها aras بود چی؟
(پست بعدی)

پست ۱ از ۳

👤 SorousH

💎 Channel: @DevelopixPython
چجوری aras رو اضافه کنیم به grades ؟ چون aras از همون حروفی که sara داره تشکیل شده با هش فانکشنی که ما نوشتیم دوباره بهمون ۴۲۳ میده و اگه باقی مانده بگیریم میشه ۳ یا درواقع همون ایندکسی که برای سارا اختصاص داده شده.
مشکل بوجود اومد... به این مشکل میگن hash collision یا تداخل هش ها!

هش فانکشنی که انتخاب کردیم شاید زیاد جالب نبود چون درواقع به ازای تمام جای گشت های یک کلمه همون هش رو بهمون میده.

هش فانکشن خوب توی hashmap ها دو تا ویژگی داره:
۱- باید محاسباتش سبک باشه. چون دائما داره برای همه ی کلید ها حساب میشه.
۲- "سعی کنه" مقدار های یونیک تولید کنه تا به hash collision بر نخوریم.

بیایم کمی تغییرش بدیم: علاوه بر اینکه از عدد اسکیشون استفاده میکنیم، بیایم اون عدد رو در جایگاهی که داره(حرف چندمه) ضرب هم بکنیم به این شکل:
def hash_func(string):
hash_value = 0
for i, char in enumerate(string, start=1):
hash_value += ord(char) * i
return hash_value

الان هش collision رو بر طرف کردیم:
for name in ("ali", "sara", "reza", "aras"):
hash_value = hash_func(name)
print(f"{name}: {hash_value} : {hash_value % 5}")
خروجیش میشه:
ali:  628  : 3
sara: 1039 : 4
reza: 1070 : 0
aras: 1076 : 1
ولی همونطور که حدس میزنید باز هم با کلید های مختلف ما به hash collision بر میخوریم... مثلا جای aras بذارید nima ...
چه کنیم؟ بیایم یه هش فانکشن معقول داشته باشیم که سعی کنه با سرعت بالا hash value رو محاسبه کنه (چیزی که الان داریم) ولی اگه collision پیش اومد رفعش کنیم! چطور؟

روش اول، separate chaining :
تو این روش میگه به جای اینکه ما بیایم slot ها رو خالی بذاریم (None) ، بیایم به جاش از لیست خالی استفاده کنیم! هر موقع hash collision داشتیم میایم اضافش میکنیم به لیست.

یعنی اگه ۴ تا دانش آموزش ما باشن: ali, sara, reza, nima
با هش فانکشن جدیدی که نوشتیم slot های ما به این صورت میشن:
grades = [
[("reza", 17), ("nima", 20)],
[],
[],
[("ali", 18)],
[("sara", 19)],
]
مشکل حل شد. الان با اینکه وقتی نمره ی نیما رو بخوایم باید قبلش یه رضا رو هم چک کنیم ولی خیلی جلو افتادیم نسبت به اینکه بخوایم همه رو چک کنیم! یعنی کلی کلید رو محاسبه نمیکنیم فقط اون چندتایی که collision داشتن سرچ میشن. (با تعداد بالا تصور کنید)

اگه دقت کنیم میبینیم هرچی hash collision بیشتر داشته باشیم به رفتار خطی بیشتر نزدیک میشیم.
این روش اول بود که پیاده سازی خیلی ساده ای هم داره. یه مشکلی ریزی داریم اینجا. یه سری فضای خالی الان توی slot های ما بوجود اومده. آیا میتونیم بیایم از این فضاها استفاده کنیم؟


روش دوم، open addressing:
شرایطی و در نظر بگیرید که الان reza و ali و sara ذخیره شدن و ما میخوایم nima رو اضافه کنیم:
grades = [
("reza", 17),
None,
None,
("ali", 18),
("sara", 19),
]
میایم nima رو هش میکنیم ایندکس و پیدا میکنیم میبینیم میشه صفر. و نگاه میکنیم میبینیم پر هست! میایم یه sequence ای تولید میکنیم به اسم probing sequence. به طوری که از همون اون ایندکسی که محاسبه کردیم شروع میشه(اینجا شد صفر برای نیما) و یه دور میزنه:
0 -> 1 -> 2 -> 3 -> 4
اگه برای ali میخواستیم probing sequence چی میشد؟
3 -> 4 -> 0 -> 1 -> 2
و به همین ترتیب میریم جلو تا به جای خالی برسیم. الان برای نیما ایندکس بعدی میشه ۱. خالی هست؟ بله. پس میذاریمش اونجا و تبدیل میشه به:
grades = [
("reza", 17),
("nima", 20),
None,
("ali", 18),
("sara", 19),
]
ما ۳ شکل probe sequence داریم:
1- linear probing
2- quadratic probing
3- double hashing

کاری که بالا کردیم linear probing بود. چون نمیخوام بیشتر از این طولانی بشه دوتای دیگه رو اینجا نمیگم(پیاده سازیش رو در انتها گذاشتم) ولی حدس زدنش سادس. مثلا تو دومی به جای اینکه دونه دونه بره بالا ، با توان های ۲ میره بالا (کمک میکنه که توده ای از کلید ها رو یک جای hash table مون نداشته باشیم پخش بشن) و آخری میگه یه هش دیگه(هش دوم) انجام بدیم برای پیدا کردن ایندکس بعدی!

اینا هر کدوم مزایا و معایبی دارن که میشه کلی دربارشون بحث کرد که کدوم کجا چرا بهتره.

پست تموم شد ولی یه سری نکته های تکمیلی باقی موند:
(پست بعدی و آخر)

پست ۲ از ۳

👤 SorousH

💎 Channel: @DevelopixPython
نکته ۱:
دیکشنری توی پایتون نمونه از associative array هست که با hashtable یا hashmap پیاده سازی شده.

نکته ۲:
این پیاده سازی از hashmap چیزی هست که همین الان تو خیلی از زبان ها برای دیکشنری، set ها توی پایتون و برای دیکشنری ها تا قبل از ورژن ۳.۶ توی پایتون استفاده میشده.
به طور کلی hashmap ها ترتیب رو حفظ نمیکنن، همونطور که دیدید ولی از پایتون ۳.۶ به بعد آقای Raymond Hettinger یه پیاده سازی جدیدی برای دیکشنری ها انجام داد به اسم raymond dict. کلیت همینه ولی یه مقدار فرق داره با چیزی که دیدیم که هم کم حجم تره هم باعث میشه ترتیب رو حفظ کنن. اگه علاقه داشتید میتونم بعدا پیاده سازی دیکشنری های جدید پایتون رو هم بگم.

نکته ۳: توی separate chaining میشه به جای لیست از linked list یا binary search tree هم استفاده کرد که باز هم هر کدوم معایب و مزایای خودشون رو دارن.

نکته ۴:
خیلی از نکات گفته نشد به دلیل اینکه نمیخواستم بیشتر از این طولانی بشه. از جمله:
- پایتون علاوه بر key و value خود هش‌ها رو هم نگه داره میکنه. چرا اینکارو میکنه؟
- این hash table عه ما به یه حدی که برسه نیاز داره تا resize بشه تا پرفورمنسش رو حفظ کنه. اگه از یه حدی بیشتر پر باشه تعداد دفعاتی که collision میگیریم بیشتر میشه و دیکشنری یا ست ما کند تر میشه.
- اگه یه کلیدی و delete کردیم تکلیف hashtable چی میشه؟ چطور باید هندل بشه؟

من همه ی انواع implementation هایی که اسمشون اومد رو به صورت کامل پیاده سازی کردم و نکاتی که وقت نشد رو توش گنجوندم. میتونید به عنوان رفرنس بهش یه نگاه بندازید:

* Open Addressing:
- Linear Probing
- Quadratic Probing
- Double Hashing Probing
* Separate Chaining
- With Dynamic Array
- With Linked List
- With Binary Search Tree

ریپازیتوری‌‌ گیت‌هاب:
https://github.com/amirsoroush/Python_Hashmaps

پست ۳ از ۳

👤 SorousH

💎 Channel: @DevelopixPython
#سوال
اجرای کدام تابع زمان کمتری نیاز دارد ⁉️

💠 جواب

✍🏻 *ژنرال*

💎 Channel: @DevelopixPython
Please open Telegram to view this post
VIEW IN TELEGRAM
درود. یه موضوع ساده ولی جالب:
همونطور که میدونید برای تولید اعداد (شبه) رندوم از ماژول random استفاده میکنیم توی پایتون. یکی از ویژگی های الگوریتم هایی که برای تولید اعداد شبه رندوم استفاده میشن این هست که باید سعی کنن به صورت یکنواخت اعداد رو توزیع کنن.
منظورم این هست که به طور مثال اگه خواستید ۱۰ هزار بار بین ۱ و ۲ و ۳ یه عددی رو انتخاب کنید باید بتونه تقریبا ۳۳۳۳ تا ۱ ، ۳۳۳۳ تا ۲ و ۳۳۳۳ تا ۳ انتخاب کنه. اول یه تست بگیریم ببینیم چقدر نزدیک هست:

> from random import randint
> from collections import Counter
>
> Counter((randint(1,3) for _ in range(10_000)))
Counter({2: 3379, 3: 3345, 1: 3276})

خیلی خوب و نزدیک بود. ولی حالا از اینکه اینا یکنواخت توزیع میشن چه استفاده‌ای میتونیم بکنیم؟
خیلی استفاده ها. یکیش که میخواستم دربارش صحبت کنم، حل بعضی مسائل مربوط به احتمالات ریاضی هست.

یه نمونش رو ببینیم:

۱۴۳ نفر در صف برای ورود به هواپیما هستند و هر نفر یک شماره صندلی متفاوت بین ۱ و ۱۴۳ دارد. تعداد صندلی های هواپیما هم دقیقا ۱۴۳ تا است. نفر اول شماره خودش را گم می‌کند و روی یک صندلی تصادفی میشند. از آن موقع به بعد هر کسی روی صندلی خودش می‌نشیند مگر این که فرد دیگری آنجا نشسته باشد و در این صورت روی یک صندلی خالی تصادفی می‌نشیند.
احتمال اینکه نفر ۱۴۳ ام روی صندلی خودش بنشیند چقدر است؟

اگه تونستین این سوال رو از راه ریاضی حل کنید که چه عالی، ولی اگر مثل من با دیدن صورت سوال راه حل ریاضیش به ذهنتون نیومد یا شک داشتید، کافیه بیاید فقط ۱ بار اون داستانی که توی صورت سوال اومده رو به کد تبدیل کنید، هرجا گفت تصادفی یا رندوم شما از random استفاده میکنید. در آخر مثلا ۱۰ هزار بار توی لوپ تکرارش کنید. به همین راحتی جواب و به دست میارید.



کلیت کار:‌ یک لیستی درست کنید از ۱۴۳ نفر که هر کدوم یه شماره صندلی ای بین ۱ تا ۱۴۳ دستشونه، برای نفر اول یه شماره به صورت رندم انتخاب کنید، بعد از نفر دوم تا آخر چک کنید که آیا صندلیش خالی یا None هست یا پره؟
اگه خالی بود بذاریدش اونجا و اگه پر بود یه شماره رندوم براش انتخاب کنید. در انتها، ما بدست آوردیم که "یک بار"ش چی میشه... آیا نفر آخر میشینه سر جاش یا نمیشینه. این جواب مهم نیست چی باشه، همین تابع رو ۱۰ هزار بار کال کنید و توی Counter بذارید.

احتمالش چقدر شد؟

👤 SorousH

💎 Channel: @DevelopixPython
💠 معرفی Mojo برای برنامه‌نویسان پایتون

🌐 خواندن مقاله

✍🏻 *ژنرال*

💎 Channel: @DevelopixPython
Please open Telegram to view this post
VIEW IN TELEGRAM
#سوال
خروجی کد زیر چیست ⁉️ (با توضیح)

✍️ *ژنرال*

💎 Channel: @DevelopixPython
Please open Telegram to view this post
VIEW IN TELEGRAM