یه شمای عالی از توانایی های مدل های زبانی و انواع های مدل های زبانی
اگه دوستاشتید مقالش رو که دوستان عزیزم زحمت انتشارش رو کشیدن رو هم مطالعه کنید.
لینک مقاله
@lython
اگه دوستاشتید مقالش رو که دوستان عزیزم زحمت انتشارش رو کشیدن رو هم مطالعه کنید.
لینک مقاله
@lython
✅ ترفند پایتونی:
آیا من میتونم یک عدد بزرگ رو به عنوان متغیر تعریف میکنم ولی وقتی میخوام بخونمش ی طوری جداش کنم که خوندنش هم راحت باشه؟
جواب: میشه، کافیه با استفاده از _ عدد رو جدا کنید تا هم خودتون به راحتی بتونید عدد رو بخونید هم تغییری تو متغیر ایجاد نشه
مثال :
testNum = 10_000_000_000
print(testNum)
>>> 10000000000
@lython
آیا من میتونم یک عدد بزرگ رو به عنوان متغیر تعریف میکنم ولی وقتی میخوام بخونمش ی طوری جداش کنم که خوندنش هم راحت باشه؟
جواب: میشه، کافیه با استفاده از _ عدد رو جدا کنید تا هم خودتون به راحتی بتونید عدد رو بخونید هم تغییری تو متغیر ایجاد نشه
مثال :
testNum = 10_000_000_000
print(testNum)
>>> 10000000000
@lython
✅ هر وقت صحبت از شیء گرایی و ارث بری میشه پای Mixin هم میاد وسط. اما دقیقا چیه؟ Mixin توی پایتون یک الگو هستش و کدهایی که از این الگو بهره میبرند کلمهی کلیدی خاصی یا چیز اضافهتری ندارند. فرض کنین ما میخواهیم یک متد جدید به یک کلاس اضافه کنیم تا
مثلا کلاسهای زیر رو در نظر بگیرید.
حالا نیاز داریم که متد play music رو هم به این کلاس ها اضافه کنیم، دوتا راه داریم. اولیش اینه که:
اما یک ایرادی وجود داره. اینجا خودمون رو تکرار کردیم. درواقع اومدیم دوبار یک تکه کد رو تکرار کردیم و این از نظر کدینگ وجه خوبی نداره. پس این راه حل ما نیست.
روش دوم اینه بیایم به بیس کلاسمون یعنی Vehicle یک متد تحت عنوان play_music اضافه کنیم.
اما در این صورت کلاس موتورسیکلت هم دارای رفتار پخش موزیک خواهد شد و این اشتباه است. اینجا است که Mixin خودش رو نشون میده. به کد زیر توجه کنید.
درواقع از کلاس PlayMusicMixin قرار نیست هیچ شیٔ ای ساخته شود و صرفا مهم این است که کارایی کلاسهای خاصی را افزایش شود.
پ.ن: اون کلمهی Mixin انتهای اسم کلاس هم قراردادیه، بهتره نوشته بشه ولی اجبار نداره.
باتشکر از @miladseyfii
@lython
`کارایی`
یا 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
✅ برنامهنویسی غیرهمزمان (Asynchronous)
برنامهنویسی غیرهمزمان یکی از مفاهیم مهم در توسعه نرمافزار است که به شما امکان میدهد عملیاتهای مختلف را به طور همزمان و بدون مسدود کردن (Blocking) برنامه اجرا کنید. این روش به ویژه برای بهبود کارایی برنامهها در زمان اجرای عملیاتهای I/O مثل درخواستهای شبکه، خواندن و نوشتن فایلها ودیگر فرایند ها مفید است.
◀️ مفاهیم کلیدی:
1. حلقه رویداد (Event Loop): هسته اصلی اجرای کدهای غیرهمزمان که مسئول مدیریت وظایف مختلف است.
2. کوروتین (Coroutine): نوع خاصی از تابع که میتواند متوقف و از سر گرفته شود. کوروتینها با
3. انتظار (Await): برای متوقف کردن اجرای یک کوروتین تا تکمیل شدن یک وظیفه دیگر استفاده میشود.
4. وظیفه (Task): یک کوروتین زمانبندی شده برای اجرا به طور همزمان با سایر وظایف.
◀️ مثال ساده:
◀️ مثال پیشرفتهتر:
@lython
برنامهنویسی غیرهمزمان یکی از مفاهیم مهم در توسعه نرمافزار است که به شما امکان میدهد عملیاتهای مختلف را به طور همزمان و بدون مسدود کردن (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
✅موارد مناسب برای استفاده از کوروتینها
◀️ عملیاتهای I/O-محور:
وقتی برنامه شما نیاز به اجرای تعداد زیادی عملیات I/O مانند خواندن و نوشتن فایل، ارتباطات شبکهای (مثل درخواستهای HTTP)، ارتباط با پایگاههای داده، و غیره دارد، کوروتینها میتوانند به طور همزمان این عملیاتها را مدیریت کنند بدون اینکه برنامه مسدود شود.
◀️ انتظار برای منابع خارجی:
زمانی که برنامه شما نیاز دارد منتظر پاسخ از سرورهای خارجی، دیتابیسها یا سایر منابع باشد. استفاده از await در کوروتینها به برنامه اجازه میدهد که در حین انتظار برای این پاسخها به اجرای سایر کدها ادامه دهد.
◀️ مدیریت تعداد زیادی از کارهای کوچک و مستقل:
وقتی باید تعداد زیادی وظایف کوچک و مستقل را مدیریت کنید که نیاز به همزمانی دارند، کوروتینها میتوانند به شما کمک کنند تا بدون سربار زیاد، این وظایف را به طور کارآمد مدیریت کنید.
◀️ زمانبندی و تأخیر در اجرای کد:
اگر نیاز دارید تا اجرای کدها را با تأخیر خاصی انجام دهید یا عملیاتهای دورهای را برنامهریزی کنید، کوروتینها میتوانند با استفاده از asyncio.sleep و سایر امکانات asyncio این کارها را به خوبی انجام دهند.
@lython
◀️ عملیاتهای I/O-محور:
وقتی برنامه شما نیاز به اجرای تعداد زیادی عملیات I/O مانند خواندن و نوشتن فایل، ارتباطات شبکهای (مثل درخواستهای HTTP)، ارتباط با پایگاههای داده، و غیره دارد، کوروتینها میتوانند به طور همزمان این عملیاتها را مدیریت کنند بدون اینکه برنامه مسدود شود.
◀️ انتظار برای منابع خارجی:
زمانی که برنامه شما نیاز دارد منتظر پاسخ از سرورهای خارجی، دیتابیسها یا سایر منابع باشد. استفاده از await در کوروتینها به برنامه اجازه میدهد که در حین انتظار برای این پاسخها به اجرای سایر کدها ادامه دهد.
◀️ مدیریت تعداد زیادی از کارهای کوچک و مستقل:
وقتی باید تعداد زیادی وظایف کوچک و مستقل را مدیریت کنید که نیاز به همزمانی دارند، کوروتینها میتوانند به شما کمک کنند تا بدون سربار زیاد، این وظایف را به طور کارآمد مدیریت کنید.
◀️ زمانبندی و تأخیر در اجرای کد:
اگر نیاز دارید تا اجرای کدها را با تأخیر خاصی انجام دهید یا عملیاتهای دورهای را برنامهریزی کنید، کوروتینها میتوانند با استفاده از asyncio.sleep و سایر امکانات asyncio این کارها را به خوبی انجام دهند.
@lython
✅Polymorphism in python
از مهمترین بحثها در شئگرایی میشه به Polymorphism اشاره کرد. معنای این مفهوم یعنی که بتونیم از یک متد یکسان برای انواع آبجکتها استفاده کنیم. کد زیر خودش گویاست.
براش مهم نیست که چه نوعی به عنوان ورودی میگیره. صرفا داره کار خودش رو میکنه چون برای جفت این کلاسها متد len با توجه به نوع ورودی تعریف شده است و این همون چندریختی یا Polymorphism هستش. خب این قدرت پایتونه که انقدر خوب همه چیو داره هماهنگ میکنه.
اما در کل سه نوع روش پیاده سازی Polymorphism وجود دارد.
1- Method Overriding
2- Method Overloading
3- Operator Overloading
------------------------------
1-Method Overriding
فرض کنید که کلاس LittleFish از کلاس Animal ارثبری میکند. در اینصورت خواهیم داشت.
نکتههای جالبی توی تکه کد بالاست. چون کلاس LittleFish از کلاس Animal ارثبری کرده پس متد feed جایگزین متد همنامی میشه که در کلاس والد موجوده. اما صرفا برای کلاس LittleFish به این شکل است و متد feed در کلاس LittleFish به اصطلاح Override شده است در مقایسه با متد feed در کلاس Animal. به کد زیر توجه کنید.
--------------------------
2-Method Overloading
حالا یه بحث دیگهای داریم تحت این عنوان بالا.
این توی پایتون پشتیبانی نمیشه. فرض کنیم توی کلاس Animal یه متد دیگه تحت عنوان breath تعریف میکنیم. مثال زیر رو ببینید.
درواقع اگر در یک کلاس دو متد همنام تعریف کنیم با این که اروری برنمیگردد ولی صرفا دومی فعال خواهد شد. مهم نیست که متد چکاری انجام میدهد صرفا نام متد است که باعث تمایز بین متدها میشود. همانطور که گفته شد این ویژگی در پایتون پشتیبانی نمیشود و متد اولی غیرفعال خواهد شد.
--------------------------
3- Operator Overloading
این ویژگی بسیار کاربردی و جالب است. درواقع این ویژگی اجازه میدهد که عملگرهای (+ - / و ... ) را برای کلاس های جدیدی که ایجاد میکنیم بازتعریف کنیم.
درواقع متد add که تعریف کردیم برای این کلاس مثل جمع برداری عمل میکند. در واقع عملگر + را برای کلاس وکتور تعریف کردیم. باز هم کد گویای مفهوم هست.
@lython
از مهمترین بحثها در شئگرایی میشه به 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()اما همانطور که میبینید در سطح کلاس Animal هنوز متد feed همانی است که در آن تعریف شدهاست.
# I eat plankton.
LittleFish().breathe()
# I breathe oxygen.
Animal().feed()
# I eat food.
--------------------------
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
Type Hinting in Python- part 2
✓ اما برای تایپ هینت انواع دادهی دیگر مثل
✓ نکته: برای دیکشنری درون آکولاد تایپ key و value دیکشنری با str و float مشخص شده است. یعنی دیکشنری که در x ریخته میشود باید از این قانون تبعیت کند تا
✓ دقت شود که کد بالا برای پایتون 3.9 به بعد است و برای نسخههای قبل از آن از کد زیر استفاده میشود که موارد زیر ابتدا باید از ماژول
✓ قابل ذکر است که تایپ هینت متدها در یک کلاس، به شکل توابع تعریف میگردد که قبلا توضیح داده شد.
✓ به کد زیر دقت کنید که مفهوم تایپ هینت
✓ اما به نظر بخش جالب ماجرا در تایپ هینت Callable است. این تایپ برای وقتی مفید است که ورودی یک تابع، یک یا چند تابع دیگر است. آنوقت میتوان توع ورودی را بوسیلهی Callable با mypy چک کرد.
سینتکس آن به شکل زیر است.
برای مثال در کد زیر دو تابع تعریف شده و به عنوان ورودی به تابع سوم داده خواهد شد.
@lython
✓ اما برای تایپ هینت انواع دادهی دیگر مثل
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
✅ لیستها در پایتون: مفاهیم پیشرفته
1️⃣ برش (Slicing)
برش به شما اجازه میدهد تا زیرمجموعهای از لیست را بدست آورید. سینتکس برش به صورت [start:stop:step] است.
2️⃣ لیستهای تودرتو (Nested Lists)
لیستها میتوانند شامل لیستهای دیگر باشند که به آنها لیستهای تودرتو گفته میشود.
3️⃣ لیستهای درک شده (List Comprehensions)
لیستهای درک شده یک راه کوتاه برای ایجاد لیستها هستند.
4️⃣ توابع کاربردی برای لیستها
پایتون توابع مختلفی را برای کار با لیستها ارائه میدهد:
5️⃣ توابع و متدهای پیشرفته
6️⃣ لیستهای چند بعدی
میتوانید لیستهای چند بعدی بسازید و با آنها کار کنید.
@lython
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
سلام رفقا امیدوارم حالتون خوب باشه
چه مدل پست بیشتر دوست دارید؟
چه مدل پست بیشتر دوست دارید؟
Anonymous Poll
42%
اطلاعات عمومی برنامه نویسی
38%
ترفند های ساده پایتون و لینوکس
68%
ترفند های حرفه ای پایتون و لینوکس
33%
توضیحات عمومی زبان پایتون و لینوکس
8%
هر چیزی بجز اینا😁😁
✅ تاپلها در پایتون: مفاهیم پیشرفته
1️⃣ تعریف تاپل
تاپلها یک نوع داده ترتیبی در پایتون هستند که بر خلاف لیستها غیرقابل تغییر (immutable) هستند. تاپلها با استفاده از پرانتزها تعریف میشوند و عناصر آنها با کاما جدا میشوند.
2️⃣ دسترسی به عناصر تاپل
میتوانید به عناصر تاپل با استفاده از اندیسها دسترسی پیدا کنید. اندیسها از صفر شروع میشوند.
3️⃣ برش (Slicing)
برش در تاپلها نیز مانند لیستها انجام میشود و به شما اجازه میدهد تا زیرمجموعهای از تاپل را بدست آورید.
4️⃣ تاپلهای تودرتو (Nested Tuples)
تاپلها میتوانند شامل تاپلها و یا هر نوع داده دیگری باشند که به آنها تاپلهای تودرتو گفته میشود.
5️⃣ توابع کاربردی برای تاپلها
پایتون توابع مختلفی را برای کار با تاپلها ارائه میدهد:
len(): طول تاپل را برمیگرداند.
sum(): مجموع عناصر عددی تاپل را محاسبه میکند.
min() و max(): کوچکترین و بزرگترین عنصر عددی تاپل را برمیگرداند.
sorted(): یک لیست مرتبشده از عناصر تاپل برمیگرداند.
6️⃣ تبدیل لیست به تاپل و برعکس
میتوانید با استفاده از توابع tuple() و list() بین لیستها و تاپلها تبدیل انجام دهید.
7️⃣ عملیاتهای متداول
عملیاتهایی مانند الحاق (concatenation) و تکرار (repetition) بر روی تاپلها امکانپذیر است.
8️⃣ تاپلهای چند بعدی
میتوانید تاپلهای چند بعدی بسازید و با آنها کار کنید.
@lython
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
✅ تفاوتهای کلیدی بین لیستها و تاپلها
قابلیت تغییر (Mutability)
لیستها:
قابل تغییر (Mutable): لیستها میتوانند پس از ایجاد تغییر کنند؛ میتوانید عناصر را اضافه، حذف یا جایگزین کنید.
تاپلها:
غیرقابل تغییر (Immutable): پس از ایجاد یک تاپل، نمیتوانید عناصر آن را تغییر دهید. این ویژگی باعث افزایش کارایی و امنیت دادهها در مواردی میشود که نیاز به تغییرات مکرر ندارند.
عملکرد (Performance)
لیستها:
کندتر: به دلیل قابلیت تغییر، لیستها دارای سربار (overhead) بیشتری هستند که میتواند منجر به کاهش کارایی در برخی موارد شود.
تاپلها:
سریعتر: از آنجا که تاپلها غیرقابل تغییر هستند، بهینهتر بوده و سربار کمتری دارند، که منجر به افزایش سرعت عملیات میشود، به خصوص در ساختارهای داده بزرگ.
استفاده حافظه (Memory Usage)
لیستها:
مصرف حافظه بیشتر: به دلیل قابلیت تغییر، لیستها برای مدیریت تغییرات به فضای اضافی نیاز دارند.
تاپلها:
مصرف حافظه کمتر: تاپلها به دلیل غیرقابل تغییر بودن و ساختار سادهتر، معمولاً فضای حافظه کمتری نسبت به لیستها اشغال میکنند.
امنیت داده (Data Integrity)
لیستها:
کمتر امن: از آنجا که لیستها قابل تغییر هستند، ممکن است بهطور ناخواسته تغییر یابند و دادهها دچار ناپایداری شوند.
تاپلها:
بیشتر امن: تاپلها به دلیل غیرقابل تغییر بودن، امنیت دادهها را تضمین میکنند و برای استفاده در موقعیتهایی که نیاز به عدم تغییر دادهها داریم، مناسبتر هستند.
کاربرد (Usage)
لیستها:
زمانی که نیاز به تغییرات مکرر دارید: برای مجموعههایی از دادهها که بهطور مداوم نیاز به اضافه کردن، حذف یا تغییر دارند، لیستها مناسبتر هستند.
تاپلها:
زمانی که نیاز به ثابت ماندن دادهها دارید: برای دادههایی که نباید تغییر کنند، مانند کلیدهای دیکشنری یا مقادیر ثابت در برنامهنویسی.
عملیاتهای مجاز
لیستها:
پشتیبانی از تمام عملیاتهای تغییرپذیری مانند append(), remove(), insert(), pop(), و غیره.
تاپلها:
پشتیبانی از عملیات دسترسی و شمارش عناصر مانند index() و count(), اما بدون قابلیت تغییر.
ترکیب دادهها (Concatenation) و تکرار (Repetition)
هر دو نوع داده از ترکیب و تکرار پشتیبانی میکنند، اما ترکیب و تکرار در تاپلها منجر به ایجاد تاپلهای جدید میشود.
تبدیل بین لیست و تاپل
گاهی اوقات نیاز به تبدیل بین این دو نوع داده وجود دارد.
نتیجهگیری
لیستها برای مواردی مناسب هستند که نیاز به تغییر، اضافه کردن یا حذف عناصر دارید. از لیستها در برنامههایی استفاده کنید که انعطافپذیری دادهها مهم است.
تاپلها برای مواردی مناسب هستند که دادهها باید ثابت بمانند و بهینهسازی عملکرد و استفاده از حافظه مهم است. از تاپلها در مواردی استفاده کنید که دادهها نباید تغییر کنند و امنیت دادهها حائز اهمیت است
@lython
قابلیت تغییر (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
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
✅ا Decorators یکی از قابلیتهای پیشرفته و بسیار قدرتمند پایتون هستند که برای تغییر یا افزایش قابلیتهای توابع یا کلاسها استفاده میشوند، بدون اینکه نیاز به تغییر کد اصلی آنها باشد. بیایید به طور کامل با این مفهوم آشنا شویم.
◀️ا Decorators در واقع توابعی هستند که به عنوان ورودی یک تابع دیگر را میگیرند و یک تابع جدید برمیگردانند که معمولاً رفتار تابع ورودی را تغییر میدهد یا بهبود میبخشد.
چرا از Decorators استفاده میکنیم؟
ا Decorators به ما این امکان را میدهند که:
کد قابل استفاده مجدد بنویسیم: میتوانیم منطق اضافی مانند ثبت لاگ، احراز هویت، بررسی نوع دادهها و ... را در یک مکان مرکزی قرار دهیم.
جداسازی منطق: میتوانیم منطق Decorators را از منطق اصلی تابع جدا کنیم.
کاهش تکرار کد: با استفاده از Decorators میتوانیم از نوشتن کد تکراری در مکانهای مختلف جلوگیری کنیم.
مثال ساده از Decorators
فرض کنید میخواهیم یک Decorators بنویسیم که زمان اجرای یک تابع را اندازهگیری کند. ابتدا، یک تابع Decorators تعریف میکنیم:
حالا میتوانیم از این Decorators برای یک تابع استفاده کنیم:
توضیح کد
تعریف Decorators: time_decorator یک تابع است که تابع دیگری (func) را به عنوان ورودی میگیرد.
تعریف یک تابع داخلی (wrapper): این تابع داخلی تابع اصلی را احاطه میکند و وظیفه اندازهگیری زمان اجرای تابع اصلی را بر عهده دارد.
استفاده از @time_decorator: با استفاده از @time_decorator قبل از تعریف تابع example_function، تابع example_function با Decorators پیچیده میشود. حالا هر وقت example_function فراخوانی شود، در واقع wrapper اجرا میشود.
نتیجه
هنگامی که example_function را فراخوانی میکنیم، خروجی به صورت زیر خواهد بود:
همانطور که میبینید، Decorators زمان اجرای تابع را محاسبه و چاپ میکند، در حالی که خود تابع اصلی بدون تغییر باقی میماند.
Decorators در پایتون قابلیتهای بسیار بیشتری دارند و میتوانند به شکلهای پیچیدهتری استفاده شوند، اما این مثال ساده به شما یک دید کلی از نحوه عملکرد آنها میدهد.
@lython
◀️ا 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
Slots (Special Methods - Part 1)
✓ یک
خروجی کد بالا به شکل زیر است. در واقع می دانیم که می توان پس از مقداردهی و ایجاد شی مورد نظر به تمام
✓قابل ذکر است که چون دسترسی به ویژگی های درون شی و تغییرات و اضافه کردن آن ها مجاز است پس با اضافه کردن ویژگی به شی پس از ایجاد شی، به
✓ اما کاربرد
1- افزایش سرعت دسترسی به ویژگی ها
2-کاهش مصرف حافظه
✓ ۲ مزیت ذکر شده مرهون استفاده از همین یک خط کد در کلاس هاست و بخصوص کلاس هایی که قرار است ویژگی های زیادی داشته باشد و همچنین اشیای فراوانی از آن کلاس ساخته شود. همانطور که گفته شد این
اگر کد بالا اجرا شود به خطای زیر برمی خوریم. قابل ذکر است که دیگر اگر
بعلاوه می توان slots را جوری تعریف کرد که در ادامه مجاز به تعریف
در این صورت امکان تعریف ویژگی
@lython
✓ یک
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
✅ آشنایی با MRO در پایتون (Method Resolution Order)
MRO یا Method Resolution Order در پایتون ترتیب جستجوی کلاسهای پایه رو برای فراخوانی متدها مشخص میکنه. این موضوع مخصوصاً توی وراثت چندگانه خیلی مهمه چون مشخص میکنه که وقتی یک متد فراخوانی میشه، پایتون از کدوم کلاس استفاده کنه.
🔎 چرا MRO مهمه؟
وقتی یک متد توی چند کلاس پایه (Parent Classes) وجود داشته باشه، پایتون از الگوریتم C3 Linearization استفاده میکنه تا ترتیب صحیح برای اجرای متدها رو پیدا کنه و از تداخلها جلوگیری کنه.
🔧 نحوه بررسی MRO
میتونی MRO یک کلاس رو با متد
🔍 مثال ساده:
📊 نتیجه MRO:
👨💻 وراثت چندگانه:
در وراثت چندگانه، پایتون MRO رو به این ترتیب محاسبه میکنه:
🔗 ترتیب MRO:
---
MRO یه مفهوم کلیدی برای مدیریت وراثت چندگانه در پایتونه که میتونه از تداخلها جلوگیری کنه و کد رو تمیزتر کنه. برای یادگیری بیشتر، الگوریتم C3 Linearization رو بررسی کن!
@lython
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