روزمرگی های یک برنامه نویس @lython Channel on Telegram

روزمرگی های یک برنامه نویس

@lython


سلام دوستان من آیدین هستم.
به پیشنهاد دوستان اینجا میخوایم جونیور فرندلی باشیم (هوای تازه‌کارها رو داشته باشیم) و مطالبی تو حوزه های لینوکس، پایتون و هوش مصنوعی به اشتراک بزاریم😃

@lython : linux python

ID: @aidinZe

http://linkedin.com/in/aidin-zehtab

روزمرگی های یک برنامه نویس (Persian)

با علاقه‌مندی به برنامه نویسی، شاید همیشه به دنبال جونیور فرندی در این حوزه باشید. اگر این چنین است، به شما کانال تلگرام "روزمرگی های یک برنامه نویس" توسط کاربر با نام کاربری @lython را پیشنهاد می‌دهیم. در این کانال، آیدین به عنوان مدیر، مطالب مفیدی در زمینه‌های لینوکس، پایتون و هوش مصنوعی به اشتراک می‌گذارد. اگر دنبال یادگیری و به‌روز بودن در این حوزه‌ها هستید، این کانال مناسب شماست. برای عضویت و دنبال کردن مطالب این کانال، می‌توانید ID @aidinZe را در تلگرام جستجو کنید. همچنین، برای اطلاعات بیشتر و ارتباط با آیدین، می‌توانید از لینک زیر استفاده کنید: http://linkedin.com/in/aidin-zehtab

روزمرگی های یک برنامه نویس

08 Oct, 05:41


آشنایی با MRO در پایتون (Method Resolution Order)

MRO یا Method Resolution Order در پایتون ترتیب جستجوی کلاس‌های پایه رو برای فراخوانی متدها مشخص می‌کنه. این موضوع مخصوصاً توی وراثت چندگانه خیلی مهمه چون مشخص می‌کنه که وقتی یک متد فراخوانی می‌شه، پایتون از کدوم کلاس استفاده کنه.

🔎 چرا MRO مهمه؟
وقتی یک متد توی چند کلاس پایه (Parent Classes) وجود داشته باشه، پایتون از الگوریتم C3 Linearization استفاده می‌کنه تا ترتیب صحیح برای اجرای متدها رو پیدا کنه و از تداخل‌ها جلوگیری کنه.

🔧 نحوه بررسی MRO
میتونی MRO یک کلاس رو با متد mro() یا ویژگی __mro__ ببینی:
class MyClass:
pass

print(MyClass.mro())
# یا
print(MyClass.__mro__)


🔍 مثال ساده:
class A:
def method(self):
print("Method in A")

class B(A):
def method(self):
print("Method in B")

class C(B):
pass

c = C()
c.method() # خروجی: Method in B

print(C.mro())


📊 نتیجه MRO:
[<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]


👨‍💻 وراثت چندگانه:
در وراثت چندگانه، پایتون MRO رو به این ترتیب محاسبه می‌کنه:
class A:
def method(self):
print("Method in A")

class B(A):
def method(self):
print("Method in B")

class C(A):
def method(self):
print("Method in C")

class D(B, C):
pass

d = D()
d.method() # خروجی: Method in B

🔗 ترتیب MRO:
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]


---

MRO یه مفهوم کلیدی برای مدیریت وراثت چندگانه در پایتونه که می‌تونه از تداخل‌ها جلوگیری کنه و کد رو تمیزتر کنه. برای یادگیری بیشتر، الگوریتم C3 Linearization رو بررسی کن!

@lython

روزمرگی های یک برنامه نویس

19 Jun, 11:12


Slots (Special Methods - Part 1)

✓ یک special attribute به نام slots هستش که با استفاده کردن از اون در کلاس هامون و بخصوص دیتا کلاس ها پرفورمنس استفاده از از کلاس رو چه در قسمت حافظه و چه در قسمت سرعت دسترسی به instance attribute ها افزایش بدهیم. به کد زیر دقت کنید، ابتدا سعی داریم یک دیتا کلاس ایجاد کنیم و نحوه ی استفاده از dict را نیز بیان کنیم.

class DataClass:
    def __init__(self, d1, d2):
        self.d1 = d1
        self.d2 = d2

object = DataClass(1, 2)
print(object.__dict__)

object.c3 = 3
print(object.__dict__)

خروجی کد بالا به شکل زیر است. در واقع می دانیم که می توان پس از مقداردهی و ایجاد شی مورد نظر به تمام Instacne Attribute های آن شی بوسیله ی dict دسترسی داشت.

{'d1': 1, 'd2': 2}
{'d1': 1, 'd2': 2, 'd3': 3}


✓قابل ذکر است که چون دسترسی به ویژگی های درون شی و تغییرات و اضافه کردن آن ها مجاز است پس با اضافه کردن ویژگی به شی پس از ایجاد شی، به Special Attribute که ذکر کردیم نdictظور __dict__ است.)

اما کاربرد Slot به چه شکل است؟

1- افزایش سرعت دسترسی به ویژگی ها
2-کاهش مصرف حافظه


✓ ۲ مزیت ذکر شده مرهون استفاده از همین یک خط کد در کلاس هاست و بخصوص کلاس هایی که قرار است ویژگی های زیادی داشته باشد و همچنین اشیای فراوانی از آن کلاس ساخته شود. همانطور که گفته شد این Special Attribute دسترسی به Attribute های درون یک کلاس را محدود خواهد کرد. و دیگر نمی توان مثل کد بالا d3 را به عنوان Instance Att به کلاس خود اضافه کنیم.
class DataClass:

    Class(1, 2)= ('d1', 'd2')

     def __init__(self, d1, d2):
         self.d1 = d1
         self.d2 = d2

object = DataClass(1, 2)
object.d3 = 5


اگر کد بالا اجرا شود به خطای زیر برمی خوریم. قابل ذکر است که دیگر اگر slots مثل کد بالا تعریف شود دیگر دسترسی به dict نیز امکان پذیر نیست.

AttributeError: 'DataClass' object has no attribute 'd3'

بعلاوه می توان slots را جوری تعریف کرد که در ادامه مجاز به تعریف Instance Attribute های خاصی پس از ایجاد شی باشیم. باز به کد زیر توجه شود.

class DataClass:

    bject.c3 = = ('d1', 'd2', 'd3')

     def __init__(self, d1, d2):
         self.d1 = d1
         self.d2 = d2

object = DataClass(1, 2)
object.d3 = 0


در این صورت امکان تعریف ویژگی d3 وجود دارد ولی ویژگی  دیگری را نمی توان تعریف کرد. این هم به خاطر این است که d3 در special attribute به نام slots تعریف شده است.

@lython

روزمرگی های یک برنامه نویس

02 Jun, 08:48


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

◀️ا Decorators در واقع توابعی هستند که به عنوان ورودی یک تابع دیگر را می‌گیرند و یک تابع جدید برمی‌گردانند که معمولاً رفتار تابع ورودی را تغییر می‌دهد یا بهبود می‌بخشد.
چرا از Decorators استفاده می‌کنیم؟

ا Decorators به ما این امکان را می‌دهند که:

کد قابل استفاده مجدد بنویسیم: می‌توانیم منطق اضافی مانند ثبت لاگ، احراز هویت، بررسی نوع داده‌ها و ... را در یک مکان مرکزی قرار دهیم.
جداسازی منطق: می‌توانیم منطق Decorators را از منطق اصلی تابع جدا کنیم.
کاهش تکرار کد: با استفاده از Decorators می‌توانیم از نوشتن کد تکراری در مکان‌های مختلف جلوگیری کنیم.

مثال ساده از Decorators

فرض کنید می‌خواهیم یک Decorators بنویسیم که زمان اجرای یک تابع را اندازه‌گیری کند. ابتدا، یک تابع Decorators تعریف می‌کنیم:


import time

def time_decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"Execution time of {func.__name__}: {end_time - start_time} seconds")
return result
return wrapper

حالا می‌توانیم از این Decorators برای یک تابع استفاده کنیم:


@time_decorator
def example_function():
time.sleep(2)
print("Function executed")

example_function()

توضیح کد

تعریف Decorators: time_decorator یک تابع است که تابع دیگری (func) را به عنوان ورودی می‌گیرد.
تعریف یک تابع داخلی (wrapper): این تابع داخلی تابع اصلی را احاطه می‌کند و وظیفه اندازه‌گیری زمان اجرای تابع اصلی را بر عهده دارد.
استفاده از @time_decorator: با استفاده از @time_decorator قبل از تعریف تابع example_function، تابع example_function با Decorators پیچیده می‌شود. حالا هر وقت example_function فراخوانی شود، در واقع wrapper اجرا می‌شود.

نتیجه

هنگامی که example_function را فراخوانی می‌کنیم، خروجی به صورت زیر خواهد بود:


Function executed
Execution time of example_function: 2.002345323562622 seconds

همانطور که می‌بینید، Decorators زمان اجرای تابع را محاسبه و چاپ می‌کند، در حالی که خود تابع اصلی بدون تغییر باقی می‌ماند.

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

روزمرگی های یک برنامه نویس

01 Jun, 06:30


Data Class in python- part 1

✓ طبق تعریف کتاب وزین Fluent Python می‌توان تعریف جالبی برای دیتا کلاس‌ها ارائه داد.
Python offers a few ways to build a simple class that is just a collection of fields, with little or no extra functionality. p163

✓ درواقع دیتا کلاس‌ها ذاتا ظرفی هستن برای نگه‌داری داده‌ها، متدها در این نوع کلاس نقش بسیار کم‌رنگی ایفا می‌کنند یا حتی می‌توان گفت، هیچ نقشی ندارند. مگر این که کاربرد متدی به نگه‌داری یا تغییر داده‌ها مربوط باشد.
به هر حال می‌توان به سه نوع نوشتن دیتا کلاس‌ها اشاره کرد.

1- @dataclasses.dataclass (python +3.7)
2- collections.namedtuple (python +2.6)
3- typing.NamedTuple (python +3.6)


✓ کتاب مثال جالبی زده است، فرض کنید که ما صرفا می‌خواهیم کلاسی تحت عنوان Coordinate تعریف کنیم که مختصات را در خود ذخیره کند.
class Coordinate:
    def __init__(self, lat, lon):
        self.lat = lat
        self.lon = lon

✓ این کلاس به راحتی قابل تعریف بود، اما ایراداتی را دارد که در ادامه به بیان آن‌ها خواهیم پرداخت. به کد زیر دقت کنید.
moscow = Coordinate(55.76, 37.62)
location = Coordinate(55.76, 37.62)
✓ دقت شود که مختصات جفت این ها یکسان است ولی وقتی  با == دو لوکیشن را مقایسه می‌کنیم به نتیجه دلخواه نخواهیم رسید زیرا مکان آن دو در حافظه درحال مقایسه است.

>>> location == moscow
False
>>> moscow
<coordinates.Coordinate object at 0x107142f10>

✓ پس دو مشکل اصلی را در حال نظاره‌ایم، یکی این که مجیک متد __repr__  را باید بازنویسی کنیم و به بازنویسی مجیک متد __eq__ نیز نیازمندیم. در ادامه از  اولین نوع دیتا کلاس استفاده خواهیم کرد. به کد زیر دقت کنید.
from dataclasess import dataclass 

@dataclass(frozen=True)
class Coordinate:
    lat: float
    lon: float

moscow = Coordinate(lat= 55.76, lon= 37.62 )
location = Coordinate(lat= 55.76, lon= 37.62 )

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

✓ مقدار frozen برابر True قرار داده شده، تا کلاس ایجاد شده immutable شود.

✓ نکته‌ی دیگری که باید در نظر گرفت، بهتر است که آرگومان‌های ورودی به صورت keyword only به دیتا کلاس برای ایجاد شیٔ داده شود زیرا ترتیب آرگومان‌های ورودی اینجا اهمیت دارد.
مشکلاتی که در تعریف قبلی کلاس Coordinate  به آن اشاره کردیم، در تعریف جدید به لطف باهوش بودن سازندگان پایتون حل شده است. کد زیر خود موضوع را روشن می‌کند.
>>>moscow == location 
True
>>>moscow
Coordinate(lat= 55.76, lon= 37.62 )

یعنی دو مجیک متد ذکر شده برای دیتاکلاس ما از پیش تعریف شده است.
@lython

روزمرگی های یک برنامه نویس

29 May, 11:30


تفاوت‌های کلیدی بین لیست‌ها و تاپل‌ها

قابلیت تغییر (Mutability)

لیست‌ها:

قابل تغییر (Mutable): لیست‌ها می‌توانند پس از ایجاد تغییر کنند؛ می‌توانید عناصر را اضافه، حذف یا جایگزین کنید.



my_list = [1, 2, 3]
my_list[0] = 4 # تغییر اولین عنصر
my_list.append(5) # اضافه کردن عنصر جدید
print(my_list) # خروجی: [4, 2, 3, 5]

تاپل‌ها:

غیرقابل تغییر (Immutable): پس از ایجاد یک تاپل، نمی‌توانید عناصر آن را تغییر دهید. این ویژگی باعث افزایش کارایی و امنیت داده‌ها در مواردی می‌شود که نیاز به تغییرات مکرر ندارند.



my_tuple = (1, 2, 3)
# my_tuple[0] = 4 # این خط خطا می‌دهد

عملکرد (Performance)

لیست‌ها:

کندتر: به دلیل قابلیت تغییر، لیست‌ها دارای سربار (overhead) بیشتری هستند که می‌تواند منجر به کاهش کارایی در برخی موارد شود.

تاپل‌ها:

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

استفاده حافظه (Memory Usage)

لیست‌ها:

مصرف حافظه بیشتر: به دلیل قابلیت تغییر، لیست‌ها برای مدیریت تغییرات به فضای اضافی نیاز دارند.

تاپل‌ها:

مصرف حافظه کمتر: تاپل‌ها به دلیل غیرقابل تغییر بودن و ساختار ساده‌تر، معمولاً فضای حافظه کمتری نسبت به لیست‌ها اشغال می‌کنند.

امنیت داده (Data Integrity)

لیست‌ها:

کمتر امن: از آنجا که لیست‌ها قابل تغییر هستند، ممکن است به‌طور ناخواسته تغییر یابند و داده‌ها دچار ناپایداری شوند.

تاپل‌ها:

بیشتر امن: تاپل‌ها به دلیل غیرقابل تغییر بودن، امنیت داده‌ها را تضمین می‌کنند و برای استفاده در موقعیت‌هایی که نیاز به عدم تغییر داده‌ها داریم، مناسب‌تر هستند.

کاربرد (Usage)

لیست‌ها:

زمانی که نیاز به تغییرات مکرر دارید: برای مجموعه‌هایی از داده‌ها که به‌طور مداوم نیاز به اضافه کردن، حذف یا تغییر دارند، لیست‌ها مناسب‌تر هستند.



my_list = [1, 2, 3]
my_list.append(4)
my_list.remove(2)
print(my_list) # خروجی: [1, 3, 4]

تاپل‌ها:

زمانی که نیاز به ثابت ماندن داده‌ها دارید: برای داده‌هایی که نباید تغییر کنند، مانند کلیدهای دیکشنری یا مقادیر ثابت در برنامه‌نویسی.



my_tuple = (1, 2, 3)
my_dict = {my_tuple: "value"} # استفاده از تاپل به عنوان کلید در دیکشنری

عملیات‌های مجاز

لیست‌ها:

پشتیبانی از تمام عملیات‌های تغییرپذیری مانند append(), remove(), insert(), pop(), و غیره.

تاپل‌ها:

پشتیبانی از عملیات دسترسی و شمارش عناصر مانند index() و count(), اما بدون قابلیت تغییر.

ترکیب داده‌ها (Concatenation) و تکرار (Repetition)
هر دو نوع داده از ترکیب و تکرار پشتیبانی می‌کنند، اما ترکیب و تکرار در تاپل‌ها منجر به ایجاد تاپل‌های جدید می‌شود.


# ترکیب
list1 = [1, 2]
list2 = [3, 4]
combined_list = list1 + list2
print(combined_list) # خروجی: [1, 2, 3, 4]

tuple1 = (1, 2)
tuple2 = (3, 4)
combined_tuple = tuple1 + tuple2
print(combined_tuple) # خروجی: (1, 2, 3, 4)

# تکرار
repeated_list = list1 * 3
print(repeated_list) # خروجی: [1, 2, 1, 2, 1, 2]

repeated_tuple = tuple1 * 3
print(repeated_tuple) # خروجی: (1, 2, 1, 2, 1, 2)

تبدیل بین لیست و تاپل

گاهی اوقات نیاز به تبدیل بین این دو نوع داده وجود دارد.


# لیست به تاپل
my_list = [1, 2, 3]
my_tuple = tuple(my_list)
print(my_tuple) # خروجی: (1, 2, 3)

# تاپل به لیست
my_tuple = (1, 2, 3)
my_list = list(my_tuple)
print(my_list) # خروجی: [1, 2, 3]

نتیجه‌گیری

لیست‌ها برای مواردی مناسب هستند که نیاز به تغییر، اضافه کردن یا حذف عناصر دارید. از لیست‌ها در برنامه‌هایی استفاده کنید که انعطاف‌پذیری داده‌ها مهم است.
تاپل‌ها برای مواردی مناسب هستند که داده‌ها باید ثابت بمانند و بهینه‌سازی عملکرد و استفاده از حافظه مهم است. از تاپل‌ها در مواردی استفاده کنید که داده‌ها نباید تغییر کنند و امنیت داده‌ها حائز اهمیت است

@lython

روزمرگی های یک برنامه نویس

29 May, 05:34


تاپل‌ها در پایتون: مفاهیم پیشرفته

1️⃣ تعریف تاپل

تاپل‌ها یک نوع داده ترتیبی در پایتون هستند که بر خلاف لیست‌ها غیرقابل تغییر (immutable) هستند. تاپل‌ها با استفاده از پرانتزها تعریف می‌شوند و عناصر آن‌ها با کاما جدا می‌شوند.


my_tuple = (1, 2, 3, 'hello', 4.5)
print(my_tuple) # خروجی: (1, 2, 3, 'hello', 4.5)

2️⃣ دسترسی به عناصر تاپل

می‌توانید به عناصر تاپل با استفاده از اندیس‌ها دسترسی پیدا کنید. اندیس‌ها از صفر شروع می‌شوند.


print(my_tuple[0]) # خروجی: 1
print(my_tuple[3]) # خروجی: hello
print(my_tuple[-1]) # خروجی: 4.5

3️⃣ برش (Slicing)

برش در تاپل‌ها نیز مانند لیست‌ها انجام می‌شود و به شما اجازه می‌دهد تا زیرمجموعه‌ای از تاپل را بدست آورید.


print(my_tuple[1:4]) # خروجی: (2, 3, 'hello')
print(my_tuple[:3]) # خروجی: (1, 2, 3)
print(my_tuple[2:]) # خروجی: (3, 'hello', 4.5)
print(my_tuple[::-1]) # خروجی: (4.5, 'hello', 3, 2, 1)


4️⃣ تاپل‌های تودرتو (Nested Tuples)

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


nested_tuple = (1, 2, (3, 4), (5, (6, 7)))
print(nested_tuple[2]) # خروجی: (3, 4)
print(nested_tuple[3][1]) # خروجی: (6, 7)
print(nested_tuple[3][1][1]) # خروجی: 7

5️⃣ توابع کاربردی برای تاپل‌ها

پایتون توابع مختلفی را برای کار با تاپل‌ها ارائه می‌دهد:

len(): طول تاپل را برمی‌گرداند.
sum(): مجموع عناصر عددی تاپل را محاسبه می‌کند.
min() و max(): کوچک‌ترین و بزرگ‌ترین عنصر عددی تاپل را برمی‌گرداند.
sorted(): یک لیست مرتب‌شده از عناصر تاپل برمی‌گرداند.


num_tuple = (3, 1, 4, 1, 5, 9, 2, 6)

print(len(num_tuple)) # خروجی: 8
print(sum(num_tuple)) # خروجی: 31
print(min(num_tuple)) # خروجی: 1
print(max(num_tuple)) # خروجی: 9
print(sorted(num_tuple)) # خروجی: [1, 1, 2, 3, 4, 5, 6, 9]

6️⃣ تبدیل لیست به تاپل و برعکس

می‌توانید با استفاده از توابع tuple() و list() بین لیست‌ها و تاپل‌ها تبدیل انجام دهید.


my_list = [1, 2, 3]
my_tuple = tuple(my_list)
print(my_tuple) # خروجی: (1, 2, 3)

new_list = list(my_tuple)
print(new_list) # خروجی: [1, 2, 3]

7️⃣ عملیات‌های متداول

عملیات‌هایی مانند الحاق (concatenation) و تکرار (repetition) بر روی تاپل‌ها امکان‌پذیر است.


tuple1 = (1, 2, 3)
tuple2 = (4, 5, 6)

# الحاق
combined_tuple = tuple1 + tuple2
print(combined_tuple) # خروجی: (1, 2, 3, 4, 5, 6)

# تکرار
repeated_tuple = tuple1 * 3
print(repeated_tuple) # خروجی: (1, 2, 3, 1, 2, 3, 1, 2, 3)

8️⃣ تاپل‌های چند بعدی

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


matrix = ((1, 2, 3),
(4, 5, 6),
(7, 8, 9))

# دسترسی به عناصر ماتریس
print(matrix[1][2]) # خروجی: 6

# پیمایش در ماتریس
for row in matrix:
for item in row:
print(item, end=' ') # خروجی: 1 2 3 4 5 6 7 8 9 (4, 5, 6),
(7, 8, 9))

# دسترسی به عناصر ماتریس
print(matrix[1][2]) # خروجی: 6

# پیمایش در ماتریس
for row in matrix:
for item in row:
print(item, end=' ') # خروجی: 1 2 3 4 5 6 7 8 9

@lython

روزمرگی های یک برنامه نویس

28 May, 13:48


لیست‌ها در پایتون: مفاهیم پیشرفته

1️⃣ برش (Slicing)

برش به شما اجازه می‌دهد تا زیرمجموعه‌ای از لیست را بدست آورید. سینتکس برش به صورت [start:stop:step] است.


my_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# برش ساده
print(my_list[2:5]) # خروجی: [2, 3, 4]

# برش با گام
print(my_list[1:8:2]) # خروجی: [1, 3, 5, 7]

# برش از ابتدا تا یک نقطه
print(my_list[:4]) # خروجی: [0, 1, 2, 3]

# برش از یک نقطه تا انتها
print(my_list[5:]) # خروجی: [5, 6, 7, 8, 9]

# برش با گام منفی (برعکس)
print(my_list[::-1]) # خروجی: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

2️⃣ لیست‌های تودرتو (Nested Lists)

لیست‌ها می‌توانند شامل لیست‌های دیگر باشند که به آن‌ها لیست‌های تودرتو گفته می‌شود.


nested_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

# دسترسی به عنصر خاص در لیست تودرتو
print(nested_list[0][1]) # خروجی: 2

# پیمایش در لیست‌های تودرتو
for sublist in nested_list:
for item in sublist:
print(item, end=' ') # خروجی: 1 2 3 4 5 6 7 8 9

3️⃣ لیست‌های درک شده (List Comprehensions)

لیست‌های درک شده یک راه کوتاه برای ایجاد لیست‌ها هستند.


# ایجاد لیستی از اعداد مربعی
squares = [x**2 for x in range(10)]
print(squares) # خروجی: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

# فیلتر کردن لیست
evens = [x for x in range(10) if x % 2 == 0]
print(evens) # خروجی: [0, 2, 4, 6, 8]

4️⃣ توابع کاربردی برای لیست‌ها

پایتون توابع مختلفی را برای کار با لیست‌ها ارائه می‌دهد:
    len(): طول لیست را برمی‌گرداند.
sum(): مجموع عناصر لیست را محاسبه می‌کند.
min() و max(): کوچک‌ترین و بزرگ‌ترین عنصر لیست را برمی‌گرداند.
sorted(): لیست را مرتب می‌کند.
reversed(): لیست را معکوس می‌کند.

my_list = [3, 1, 4, 1, 5, 9, 2, 6, 5]

print(len(my_list)) # خروجی: 9
print(sum(my_list)) # خروجی: 36
print(min(my_list)) # خروجی: 1
print(max(my_list)) # خروجی: 9
print(sorted(my_list)) # خروجی: [1, 1, 2, 3, 4, 5, 5, 6, 9]
print(list(reversed(my_list))) # خروجی: [5, 6, 2, 9, 5, 1, 4, 1, 3]

5️⃣ توابع و متدهای پیشرفته
    index(): اندیس اولین وقوع عنصر مورد نظر را برمی‌گرداند.
count(): تعداد وقوع یک عنصر را در لیست برمی‌گرداند.
insert(): یک عنصر را در اندیس مشخصی اضافه می‌کند.
pop(): عنصر با اندیس مشخصی را حذف و برمی‌گرداند.
remove(): اولین وقوع عنصر مورد نظر را حذف می‌کند.
clear(): تمام عناصر لیست را حذف می‌کند.


my_list = [1, 2, 3, 2, 4, 2]

print(my_list.index(2)) # خروجی: 1
print(my_list.count(2)) # خروجی: 3

my_list.insert(3, 'a')
print(my_list) # خروجی: [1, 2, 3, 'a', 2, 4, 2]

print(my_list.pop(3)) # خروجی: 'a'
print(my_list) # خروجی: [1, 2, 3, 2, 4, 2]

my_list.remove(2)
print(my_list) # خروجی: [1, 3, 2, 4, 2]

my_list.clear()
print(my_list) # خروجی: []


6️⃣ لیست‌های چند بعدی

می‌توانید لیست‌های چند بعدی بسازید و با آن‌ها کار کنید.


matrix = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]

# دسترسی به عناصر ماتریس
print(matrix[1][2]) # خروجی: 6

# پیمایش در ماتریس
for row in matrix:
for item in row:
print(item, end=' ') # خروجی: 1 2 3 4 5 6 7 8 9

@lython

روزمرگی های یک برنامه نویس

25 May, 07:22


Type Hinting in Python- part 2

✓ اما برای تایپ هینت انواع داده‌ی دیگر مثل list , set و dict ها و ... خواهیم داشت:
x: list[int] = [1]
x: set[int] = {6, 7}
x: dict[str, float] = {"num": 2.0}
x: tuple[str, float] = ("yes", 7.5)

✓ نکته: برای دیکشنری درون آکولاد تایپ key و value  دیکشنری با str و float  مشخص شده است. یعنی دیکشنری که در x ریخته می‌شود باید از این قانون تبعیت کند تا mypy اررور برنگرداند.

✓ دقت شود که کد بالا برای پایتون 3.9 به بعد است و برای نسخه‌های قبل از آن از کد زیر استفاده می‌شود که موارد زیر ابتدا باید از ماژول typing ایمپورت شوند.
from typing import List, Set, Dict, Tuple
x: List[int] = [1]
x: Set[int] = {6, 7}
x: Dict[str, float] = {"field": 2.0}
x: Tuple[int, str, float] = (3, "yes", 7.5)

✓ قابل ذکر است که تایپ هینت متد‌ها در یک کلاس، به شکل توابع تعریف می‌گردد که قبلا توضیح داده شد.

✓ به کد زیر دقت کنید که مفهوم تایپ هینت Any را می‌رساند. Any به معنای هر توع تایپی در نظر گرفته می‌شود. در واقع اگر هیچ تایپی برای متغیری تعریف نگردد، برای آن Any لحاظ می‌گردد. برای مثال می‌توان به متغیر x لیست، دیکشنری کلاس تابع و یا هر ورودی دیگری داد. دو تابع زیر که تعریف شده در واقع از نظر mypy یکی است.
from typing import Any

def func1(x):
    pass

def func2(x: Any):
    pass

✓ اما به نظر بخش جالب ماجرا در تایپ هینت Callable است. این تایپ برای وقتی مفید است که ورودی یک تابع، یک یا چند تابع دیگر است. آنوقت می‌توان توع ورودی را بوسیله‌ی Callable  با mypy چک کرد.
سینتکس آن به شکل زیر است.
Callable[[arg1, arg2, ...], return type]

برای مثال در کد زیر دو تابع تعریف شده و به عنوان ورودی به تابع سوم داده خواهد شد.

def func1(a: int, b: str) -> None:
    pass

def func2(results: Any) -> None:
    pass

def func3(d: Callable[[int, str], None], c: Callable[[Any], None]) -> None:
    pass


@lython

روزمرگی های یک برنامه نویس

21 May, 09:00


Polymorphism in python

از مهم‌ترین بحث‌ها در شئ‌گرایی میشه به Polymorphism اشاره کرد. معنای این مفهوم یعنی که بتونیم از یک متد یکسان برای انواع آبجکت‌ها استفاده کنیم. کد زیر خودش گویاست.

text = 'Hello World'
numbers = [1, 2, 3]
print(len(text)) # 11
print(len(numbers)) # 3

براش مهم نیست که چه نوعی به عنوان ورودی می‌گیره. صرفا داره کار خودش رو می‌کنه چون برای جفت این کلاس‌ها متد len با توجه به نوع ورودی تعریف شده است و این همون چندریختی یا Polymorphism هستش. خب این قدرت پایتونه که انقدر خوب همه چیو داره هماهنگ می‌کنه.

اما در کل سه نوع روش پیاده سازی Polymorphism وجود دارد.
1- Method Overriding
2- Method Overloading
3- Operator Overloading
------------------------------
1-Method Overriding

فرض کنید که کلاس LittleFish از کلاس Animal ارث‌بری می‌کند. در این‌صورت خواهیم داشت.
class Animal:
def breathe(self):
print("I breathe oxygen.")

def feed(self):
print("I eat food.")

class LittleFish(Animal):
def feed(self):
print("I eat plankton.")

نکته‌های جالبی توی تکه کد بالاست. چون کلاس LittleFish از کلاس Animal ارث‌بری کرده پس متد feed جایگزین متد همنامی میشه که در کلاس والد موجوده. اما صرفا برای کلاس LittleFish به این شکل است و متد feed در کلاس LittleFish به اصطلاح Override شده است در مقایسه با متد feed در کلاس Animal. به کد زیر توجه کنید.
LittleFish().feed()   
# I eat plankton.
LittleFish().breathe()
# I breathe oxygen.
Animal().feed()
# I eat food.
اما همانطور که می‌بینید در سطح کلاس Animal هنوز متد feed همانی است که در آن تعریف شده‌است.

--------------------------
2-Method Overloading
حالا یه بحث دیگه‌ای داریم تحت این عنوان بالا.
این توی پایتون پشتیبانی نمیشه. فرض کنیم توی کلاس Animal یه متد دیگه تحت عنوان breath تعریف می‌کنیم‌. مثال زیر رو ببینید.
class Animal:
def breathe(self):
print('I breathe oxygen.')

def breathe(self):
print('I breathe O2 + N2.')

درواقع اگر در یک کلاس دو متد همنام تعریف کنیم با این که اروری برنمی‌گردد ولی صرفا دومی فعال خواهد شد. مهم نیست که متد چکاری انجام می‌دهد صرفا نام متد است که باعث تمایز بین متد‌ها می‌شود. همانطور که گفته شد این ویژگی در پایتون پشتیبانی نمی‌شود و متد اولی غیرفعال خواهد شد.

--------------------------
3- Operator Overloading
این ویژگی بسیار کاربردی و جالب است. درواقع این ویژگی اجازه می‌دهد که عملگرهای (+ - / و ... ) را برای کلاس های جدیدی که ایجاد می‌کنیم بازتعریف کنیم‌.
class Vector:
def __init__(self, x, y, z):
self.x = x
self.y = y
        self.z = z

def __add__(self, other):
x = self.x +other.x
y = self.y + other.y
z = self.z + other.z
return Vector(x, y, z)

درواقع متد add که تعریف کردیم برای این کلاس مثل جمع برداری عمل می‌کند. در واقع عملگر + را برای کلاس وکتور تعریف کردیم. باز هم کد گویای مفهوم هست.
Vec1 = Vector(1, 2 ,3)
vec2 = Vector(1, 1, 1)
vec_add = vec1 + vec2
vec_add.x # 2
vec_add.y # 3
vec_add.z # 4


@lython

روزمرگی های یک برنامه نویس

19 May, 07:53


موارد مناسب برای استفاده از کوروتین‌ها

◀️ عملیات‌های I/O-محور:
وقتی برنامه شما نیاز به اجرای تعداد زیادی عملیات I/O مانند خواندن و نوشتن فایل، ارتباطات شبکه‌ای (مثل درخواست‌های HTTP)، ارتباط با پایگاه‌های داده، و غیره دارد، کوروتین‌ها می‌توانند به طور همزمان این عملیات‌ها را مدیریت کنند بدون اینکه برنامه مسدود شود.

◀️ انتظار برای منابع خارجی:
زمانی که برنامه شما نیاز دارد منتظر پاسخ از سرورهای خارجی، دیتابیس‌ها یا سایر منابع باشد. استفاده از await در کوروتین‌ها به برنامه اجازه می‌دهد که در حین انتظار برای این پاسخ‌ها به اجرای سایر کدها ادامه دهد.

◀️ مدیریت تعداد زیادی از کارهای کوچک و مستقل:
وقتی باید تعداد زیادی وظایف کوچک و مستقل را مدیریت کنید که نیاز به همزمانی دارند، کوروتین‌ها می‌توانند به شما کمک کنند تا بدون سربار زیاد، این وظایف را به طور کارآمد مدیریت کنید.

◀️ زمانبندی و تأخیر در اجرای کد:
اگر نیاز دارید تا اجرای کدها را با تأخیر خاصی انجام دهید یا عملیات‌های دوره‌ای را برنامه‌ریزی کنید، کوروتین‌ها می‌توانند با استفاده از asyncio.sleep و سایر امکانات asyncio این کارها را به خوبی انجام دهند.
@lython

روزمرگی های یک برنامه نویس

18 May, 09:03


برنامه‌نویسی غیرهمزمان (Asynchronous)

برنامه‌نویسی غیرهمزمان یکی از مفاهیم مهم در توسعه نرم‌افزار است که به شما امکان می‌دهد عملیات‌های مختلف را به طور همزمان و بدون مسدود کردن (Blocking) برنامه اجرا کنید. این روش به ویژه برای بهبود کارایی برنامه‌ها در زمان اجرای عملیات‌های I/O مثل درخواست‌های شبکه، خواندن و نوشتن فایل‌ها ودیگر فرایند ها مفید است.

◀️ مفاهیم کلیدی:

1. حلقه رویداد (Event Loop): هسته اصلی اجرای کدهای غیرهمزمان که مسئول مدیریت وظایف مختلف است.
2. کوروتین (Coroutine): نوع خاصی از تابع که می‌تواند متوقف و از سر گرفته شود. کوروتین‌ها با async def تعریف می‌شوند.
3. انتظار (Await): برای متوقف کردن اجرای یک کوروتین تا تکمیل شدن یک وظیفه دیگر استفاده می‌شود.
4. وظیفه (Task): یک کوروتین زمان‌بندی شده برای اجرا به طور همزمان با سایر وظایف.

◀️ مثال ساده:

import asyncio

async def say_hello():
print("hello!")
await asyncio.sleep(1) # delay simulation
print("world!")

asyncio.run(say_hello())


◀️ مثال پیشرفته‌تر:

import asyncio

async def fetch_data(name, delay):
print(f"started {name}")
await asyncio.sleep(delay)
print(f"ended {name}")
return f"result {name}"

async def main():
tasks = [
asyncio.create_task(fetch_data('data 1', 2)),
asyncio.create_task(fetch_data('data 2', 3)),
asyncio.create_task(fetch_data('data 3', 1)),
]
results = await asyncio.gather(*tasks)
print("results:", results)

asyncio.run(main())


@lython

روزمرگی های یک برنامه نویس

29 Apr, 05:27


هر وقت صحبت از شیء گرایی و ارث بری میشه پای Mixin هم میاد وسط. اما دقیقا چیه؟ Mixin توی پایتون یک الگو هستش و کدهایی که از این الگو بهره می‌برند کلمه‌ی کلیدی خاصی یا چیز اضافه‌تری ندارند. فرض کنین ما می‌خواهیم یک متد جدید به یک کلاس اضافه کنیم تا `کارایی` یا Functionality اون رو زیاد کنیم. اینجا میشه از Mixin استفاده کرد.
مثلا کلاس‌های زیر رو در نظر بگیرید.
class Vehicle:
    pass

class Car(Vehicle):
    pass

class Van(Vehicle):
    pass

class Motorcycle(Vehicle):
    pass

حالا نیاز داریم که متد play music رو هم به این کلاس ها اضافه کنیم، دوتا راه داریم. اولیش اینه که:
class Vehicle:
    pass

class Car(Vehicle):

    def play_music(self):
        print("play_music")

class Van(Vehicle):

    def play_music(self):
        print("play_music")
   
class Motorcycle(Vehicle):
    pass

اما یک ایرادی وجود داره. اینجا خودمون رو تکرار کردیم. درواقع اومدیم دوبار یک تکه کد رو تکرار کردیم و این از نظر کدینگ وجه خوبی نداره. پس این راه حل ما نیست.
روش دوم اینه بیایم به بیس کلاسمون یعنی Vehicle یک متد تحت عنوان play_music اضافه کنیم.

class Vehicle:
    def play_music(self):
        print("play_music")

class Car(Vehicle):
    pass

class Van(Vehicle):
    pass

class Motorcycle(Vehicle):
    pass

اما در این صورت کلاس موتورسیکلت هم دارای رفتار پخش موزیک خواهد شد و این اشتباه است. اینجا است که Mixin خودش رو نشون می‌ده. به کد زیر توجه کنید.
class Vehicle:
    pass

class PlayMusicMixin:
    def play_music(self):
        print("play_music")

class Car(Vehicle, PlayMusicMixin):
    pass

class Van(Vehicle, PlayMusicMixin):
    pass

class Motorcycle(Vehicle):
    pass

درواقع از کلاس PlayMusicMixin قرار نیست هیچ شیٔ ای ساخته شود و صرفا مهم این است که کارایی کلاس‌های خاصی را افزایش شود.
پ.ن: اون کلمه‌ی Mixin انتهای اسم کلاس هم قراردادیه، بهتره نوشته بشه ولی اجبار نداره.

باتشکر از @miladseyfii

@lython

روزمرگی های یک برنامه نویس

13 Apr, 04:19


اسلاید کامل همه چیز در مورد scipy
با تشکر از نویسندگان😃
@lython

روزمرگی های یک برنامه نویس

22 Mar, 06:08


ترفند پایتونی:
آیا من میتونم یک عدد بزرگ رو به عنوان متغیر تعریف میکنم ولی وقتی میخوام بخونمش ی طوری جداش کنم که خوندنش هم راحت باشه؟
جواب: میشه، کافیه با استفاده از _ عدد رو جدا کنید تا هم خودتون به راحتی بتونید عدد رو بخونید هم تغییری تو متغیر ایجاد نشه
مثال :
testNum = 10_000_000_000
print(testNum)
>>> 10000000000

@lython

روزمرگی های یک برنامه نویس

06 Mar, 11:20


Python tools used in ML😃
@lython

روزمرگی های یک برنامه نویس

18 Feb, 19:12


یه شمای عالی از توانایی های مدل های زبانی و انواع های مدل های زبانی
اگه دوستاشتید مقالش رو که دوستان عزیزم زحمت انتشارش رو کشیدن رو هم مطالعه کنید.
لینک مقاله
@lython