برنامه نویسی

رابط در پایتون: مفهوم ، کاربرد و مناطق استفاده

در میان پارادایم های برنامه نویسی با جهت گیری شی (OOP) ، رابط ها یکی از مفاهیم مهم است که برای افزایش انعطاف پذیری ، مدولار بودن و پایداری کد (رابط ها) استفاده می شود. رابط ها به عنوان نوعی قرارداد یا مشخصات خدمت می کنند که تعریف می کند که چگونه یک کلاس یا شیء باید در دنیای خارج ظاهر شود ، یعنی روش ها و (گاهی اوقات). ایده اصلی این است که به جای جزئیات نحوه عملکرد یک شیء ، روی کارهایی که می تواند انجام دهد تمرکز کنید.

در بسیاری از زبانهای OOP از نوع استاتیک (مانند جاوا ، C#) ، رابط ها یک بخش اساسی از زبان و با کلمات کلیدی خاص هستند (معمولاً interfaceآنها تعریف شده اند. در این زبان ها ، هنگامی که یک کلاس “رابط کاربری” را اجرا کرد ، موظف است تمام روش های تعریف شده در آن رابط را ارائه دهد و کامپایلر آن را کنترل می کند.

با این حال ، پایتون از روشی متفاوت پیروی می کند. پایتون یک کلمه کلیدی یا مکانیسم رابط جامد ندارد که شبیه جاوا یا C#باشد. ماهیت پویا پایتون و فلسفه “تایپ کردن اردک” باعث می شود رفتارهای شبیه به رابط به روشهای مختلف و انعطاف پذیر بدست آید.

در این راهنما ، مفهوم رابط در زمینه OOP عمومی را مورد بحث قرار می دهد ، بحث کنید که چرا پایتون مکانیسم رابط مستقیمی ندارد و روشهای اصلی مورد استفاده برای ایجاد و استفاده از ساختارهای شبیه رابط در پایتون – تایپ اردک ، پروتکل های کلاسهای اساسی انتزاعی (ABC) و پایتون 3.8typing.Protocol) – ما به تفصیل بررسی خواهیم کرد. علاوه بر این ، ما مزایا ، مضرات این رویکردها ، معایب و مناطق استفاده و نمونه هایی را نشان خواهیم داد که نشان می دهد کدام روش مناسب تر است.

قسمت 1: رابط چیست؟ پیشینه مفهومی
در ابتدایی ترین معنای خود ، رابط ساختاری است که امضاهای یک کلاس یا شیء را به جهان خارج تعریف می کند. رابط ها نحوه اجرای این روش ها را مشخص نمی کنند. آنها فقط تعریف می کنند که کدام روش ها باید وجود داشته باشند و چه نوع پارامترهایی را باید در نظر بگیرند و چه نوع مقادیری را باید برگردانند (به برخی از زبان ها).

ویژگی های اساسی:

قرارداد/مشخصات: یک کلاس به عنوان قراردادی عمل می کند که تضمین می کند یک مجموعه استعداد خاص خواهد داشت.
انتزاع -جهت دار: بر آنچه شی می تواند انجام دهد تمرکز می کند ، نه به “چگونه”. جزئیات اجرای را پنهان می کند.
اجرای شامل (به طور سنتی) نیست: فقط شامل امضاهای متد است. کدهای واقعی این روش ها توسط کلاسهایی ارائه می شود که دلالت بر رابط دارند. (توجه: روشهای پیش فرض در نسخه های مدرن Java/C# اضافه شده است).
اجرای چندگانه: یک کلاس معمولاً چندین رابط را پیاده سازی می کند ، بنابراین مجموعه های مهارت های مختلفی را گرد هم می آورد.
قیاس: سوکت الکتریکی و پلاگین

به یک خروجی دیواری فکر کنید. این پریز یک رابط استاندارد برای اتصال دستگاه های برقی (تعداد مشخصی از سوراخ ها ، ولتاژ خاص و استاندارد فعلی) ارائه می دهد. دستگاه های الکتریکی مختلف (لامپ ها ، رایانه ، سشوار) دارای یک پلاگین هستند که متناسب با این رابط است. اگرچه ساختار داخلی و روش دستگاه ها کاملاً متفاوت است (پیاده سازی های مختلف) ، همه آنها می توانند به آنها وصل شوند و کار کنند تا زمانی که در همان رابط سوکت قرار بگیرند. سوکت تعریف می کند که دستگاه باید چه کاری انجام دهد (برای خرید برق) ، اما نحوه استفاده از آن را تعریف نمی کند (نور یا فرآیند تولید می کند). به همین ترتیب ، رابط ها یک “بندر” یا “انتظار” را که کلاس ها باید دنبال کنند تعریف می کنند.

فصل 2: ​​اهمیت و مزایای رابط ها در طراحی نرم افزار
رابط ها (یا ساختارهای مشابه در پایتون) در طراحی نرم افزار سهم بسزایی دارند:

جفت گشاد:
سود: وابستگی بین مؤلفه های مختلف کد را کاهش می دهد. یکی از مؤلفه ها به اجرای کلاس خاص دیگر وابسته نیست ، بلکه فقط به رابط مورد نیاز خود است. این تضمین می کند که سایر مؤلفه ها تحت تأثیر قرار نمی گیرند تا زمانی که رابط در هنگام تغییر یک مؤلفه یکسان باشد.
مثال: یک ماژول گزارش دهی می تواند برای گرفتن داده ها از یک رابط کاربری داده طراحی شود. این ماژول علاقه ای به این ندارد که آیا داده ها از یک پرونده ، پایگاه داده یا API تهیه می شوند. این فقط روش data_getir () را تعریف می کند که توسط رابط Verikiagi تعریف شده است.
پشتیبانی از پلی مورفیسم:
سود: رابط ها اساس پلی مورفیسم را تشکیل می دهند. از اشیاء کلاسهای مختلف که دلالت بر همان رابط کاربری دارند ، می توانند از طریق مرجع نوع رابط به صورت متقابل استفاده شوند. این به شما امکان می دهد کد عمومی و انعطاف پذیر تری بنویسید.
مثال: پیاده سازی های کلامی مختلف (پرونده ها ، apihagi) را می توان در یک لیست نگه داشت و با یک چرخه از همه آنها عبور کرد.
تغییرپذیری و قابلیت آزمایش:
فایده: با اتصال شل ، می توان به راحتی اجرای سایر مؤلفه های مورد استفاده توسط یک مؤلفه را به راحتی جایگزین کرد (به عنوان مثال ، یک شیء پایگاه داده کاذب به جای پایگاه داده واقعی در طول آزمون). این کار نوشتن تست های واحد را تسهیل می کند.
طراحی قرارداد و قابل فهم:
فایده: رابط ها مسئولیت ها و توانایی های یک کلاس را در برابر جهان خارج به وضوح تعریف می کنند. این امر درک هدف کلاس و نحوه استفاده از آن را آسان تر می کند و به عنوان یک قرارداد طراحی عمل می کند.
توسعه موازی:
فایده: پس از تعریف رابط ، تیم ها یا توسعه دهندگان مختلف می توانند مؤلفه هایی را ایجاد کنند که این رابط را همزمان استفاده و پیاده سازی کنند ، زیرا نقطه تعامل (رابط) بین آنها مشخص است.
فصل 3: رابط در پایتون: چرا متفاوت است؟
فلسفه طراحی پایتون ، به ویژه تایپ کردن پویا و تایپ کردن اردک ، آن را از زبانها بر اساس تعاریف رابط جامد متمایز می کند.

نوع پویا: انواع متغیرها در پایتون در زمان کار تعیین می شوند. به جای نیاز به عملکردی برای گرفتن اشیاء از یک نوع خاص ، معمولاً مورد بررسی قرار می گیرد که آیا این شی رفتارهای انتظار داشته باشد یا خیر.
تایپ کردن اردک: “اگر او مانند اردک قدم می زند و مانند اردک درگیر است ، احتمالاً اردک است.” فلسفه پایتون به جای اینکه به کلاس یک شی یا رابط های اجرا شده توسط یک شیء نگاه کند ، بررسی می کند که آیا این روش یا ویژگی های مورد نیاز خود دارد. اگر او آن را داشته باشد ، از آن استفاده می کند.
به دلیل این فلسفه ، کلمه کلیدی رابط مانند زبان اصلی پایتون به طور مستقیم مورد نیاز نبود. اغلب ، هر شی با رفتارهای مورد انتظار پذیرفته می شود. با این حال ، این انعطاف پذیری می تواند منجر به مضراتی در پروژه های بزرگ یا در مواردی شود که به ضمانت های خاصی نیاز باشد (به عنوان مثال ، خطاهای زمان کار ، قراردادهای نامشخص).

به همین دلیل ، پایتون مکانیسم های مختلفی را برای ایجاد ساختارهای شبیه به رابط ارائه می دهد:

قسمت 4: روشهای کاربرد رابط در پایتون
اگرچه هیچ رابط جامعی در پایتون وجود ندارد ، رویکردهایی وجود دارد که عملکردهای مشابهی را مشاهده می کنند و در سطوح مختلف اطمینان را ارائه می دهند:

4.1 تایپ کردن اردک – رابط DAMMI
این رایج ترین و “پایتونیک” ترین رویکرد است. در اینجا هیچ تعریف رسمی رابط وجود ندارد. یک عملکرد یا روش فرض می کند که شیء داده شده به آن روش های خاصی دارد و مستقیماً آنها را صدا می کند. اگر شیء آن روش ها را داشته باشد ، اگر اینگونه نباشد ، AttributeError آن را پرتاب می کند.

کلاس pdfrapor:
def olusures (خود ، veri):
چاپ (F “گزارش PDF ایجاد شده است: {Data}”)
# … منطق ایجاد PDF …
بازگشت “rapor.pdf”
کلاس اکسلراپور:
انحراف (خود ، داده): # نام آرگومان ممکن است متفاوت باشد ، اما نام روش یکسان است
چاپ (F “گزارش اکسل در حال ایجاد است: {داده}”)
# … منطق آفرینش اکسل …
بازگشت “rapor.xlsx”
کلاس htmlrapor:
انحراف (خود ، محتوا): # نام استدلال ممکن است متفاوت باشد
چاپ (F “گزارش HTML ایجاد شده است: {محتوا}”)
# … HTML ایجاد منطق …
بازگشت “rapor.html”
پایگاه داده کلاس:
def yedk_al (خود):
چاپ (“پشتیبان گیری از پایگاه داده …”)
def report_olusturucu (گزارش_nesnesi ، گزارش_ v):
“” “
این هر شیء را با روش “ایجاد” می پذیرد.
به نوع شی نگاه نمی کند.
“” “
سعی کنید:
file_adi = گزارش_nesnesi.olustur (گزارش_ v)
چاپ (F “گزارش با موفقیت ایجاد شده است: {file_adi}”)
به جز AttributeError:
چاپ (“خطا: شیء ارائه شده” روش “ندارد.”)
به جز استثنا به عنوان E:
چاپ (f “خطا در هنگام ایجاد گزارش: {e}”)

pdf_rap = pdfrapor ()
excel_rap = excelrapor ()
html_rap = htmlrapor ()
BACKUP = پایگاه داده پایگاه داده ()
داده ها = [“veri1”, “veri2”, “veri3”]چاپ (“— تایپ کردن اردک ایجاد گزارش —“)
report_olusturucu (pdf_rap ، داده ها)
چاپ (“-” * 15)
گزارش
چاپ (“-” * 15)
Report_olusturucu (html_rap ، داده ها)
چاپ (“-” * 15)
Report_outurucular (پشتیبان گیری ، داده)
جوانب مثبت: بسیار انعطاف پذیر ، حداقل کد قالب ، توسعه سریع.
منفی: هیچ ضمانت قرارداد وجود ندارد ، خطاها در زمان کار رخ می دهد ، که می تواند مشخص باشد که کدام روش ها انتظار می رود ، تجزیه و تحلیل استاتیک دشوار می شود.
4.2 کلاسهای اساسی چکیده (کلاسهای پایه انتزاعی – ABC) – قرارداد باز
ماژول ABC به ما امکان می دهد کلاسهایی را که نمی توانند مستقیماً از بین بروند و زیر کلاسهای زیر را مجبور به اجرای روشهای خاص کنیم ، شناسایی کنیم. این نزدیکترین رویکرد برای تعریف یک رابط رسمی در پایتون است.

وارد کردن ABC
کلاس iraporolutiturucu (abc.abc): # یک کنوانسیون است که نشان می دهد این یک رابط است.
“” “کلاس اساسی انتزاعی (رابط) برای فرآیند ایجاد گزارش.” “” “
@abc.abstractmethod
def olusures (خود ، veri):
“” “گزارشی را از داده های داده شده ایجاد می کند و نام پرونده را برمی گرداند. “” “”
عبور
@abc.abstractmethod
def supported_format (خود):
“” “قالب گزارش را برمی گرداند (به عنوان مثال PDF” ، “XLSX”). ” “” “
عبور
Def Logla (خود ، پیام): # همچنین می تواند روش بتونی (بتن) باشد
چاپ (F “[LOG – {self.desteklenen_format()}]: {پیام} “)

کلاس pdfraporlayici (iraporolusturucu):
def olusures (خود ، veri):
self.logla (f “گزارش PDF ایجاد شده است: {data}”)
# … منطق ایجاد PDF …
بازگشت “rapor.pdf”
def supported_format (خود):
بازگشت “PDF”
کلاس Excelraporlayici (iraporolusturucu):
def olusures (خود ، veri):
self.logla (f “گزارش اکسل ایجاد شده است: {data}”)
# … منطق آفرینش اکسل …
بازگشت “rapor.xlsx”
def supported_format (خود):
بازگشت “xlsx”

# olustur() metodunu implemente etmediği için TypeError alır!
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

def report_uret_uret (گزارشگر: iraporolusturor ، داده ها): # ABC می تواند به عنوان سرنخ ها استفاده شود
“” “گزارش هایی را با استفاده از گزارشگر داده شده تهیه می کند.” “”
چاپ (f “\ n {گزارش دهی .desteklen_format ()} فرمت در قالب تولید می شود …”)
اگر isinstance.
پرونده = گزارش Outur (داده ها)
چاپ (f “پرونده تولید شده: {پرونده}”)
دیگری:
چاپ (“خطا: نوع گزارش void.”)
pdf_rap2 = pdfraporlayici ()
excel_rap2 = excelraporlayici ()

data = {“a”: 1 ، “b”: 2}
Report_Uret (PDF_RAP2 ، داده ها)
Report_Uret (excel_rap2 ، داده ها)
جوانب مثبت: قرارداد باز ، تعهدات اجرای ، خطاها را زودتر (هنگام ایجاد یک شیء) ضبط می کند ، قصد طراحی ، isinstance () و isubclass () را می توان با استفاده از.
CVS: به کد قالب بیشتری نیاز دارد ، یک رابطه وراثت را برقرار می کند (گاهی اوقات نه) ، به اندازه تایپ کردن اردک انعطاف پذیر نیست.
4.3 پروتکل ها (typing.Protocol) – زیرنویس های ساختاری (پایتون 3.8+)
پروتکل ها راهی برای شناسایی رابط مشابه ABC هستند ، اما تفاوت اصلی این است که به میراث من اعتماد نمی کند. از نظر ساختاری مشخص شده است که آیا یک کلاس از پروتکل استفاده نمی کند و آیا کلاس دارای روش ها و صلاحیت ها (با امضاهای مناسب) است که در پروتکل تعریف شده است. کلاس نیازی به ارث پروتکل به وضوح ندارد.

این ترکیب انعطاف پذیری تایپ اردک را با یک قرارداد رسمی که می تواند توسط کنترل کننده های نوع استاتیک (مانند MYPY) کنترل شود ، ترکیب می کند.

از تایپ پروتکل واردات ، لیست
کلاس خوان (پروتکل): # Typing.Protocol وراثت
“” “پروتکل تعریف روند خواندن (رابط ساختاری).” “” “
def read (self) -> str: # signature و type ticks تعریف شده است
… # # اجرای به جای “…” یا “پاس” استفاده می شود
def kapat (خود) -> هیچ:

پرونده کلاس:
دنباله شروع کردن(خود ، جاده):
self.yol = جاده
چاپ (f “پرونده باز شده: {جاده}”)
def oku (خود) -> str:
چاپ (f “” {self.yol} “خوانده می شود …”)
بازگشت f “'{self.yol}'”
def kapat (خود) -> هیچ:
چاپ (f “پرونده بسته: {self.yol}”)
کلاس Soket:
دنباله شروع کردن(خود ، Adres):
self.ads = آدرس
چاپ (f “سوکت متصل: {آدرس}”)
def oku (خود) -> str:
چاپ (از “سوکت {self.adres}” بخوانید … “)
بازگشت به “داده های سوکت”
def kapat (خود) -> هیچ:
چاپ (f “سوکت بسته: {self.adres}”)
def ek_metot (خود): # روش تکمیلی در پروتکل
چاپ (“روش ویژه سوکت”)
کلاس به دروغ
def oku (خود) -> str:
“خواننده اشتباه” را برگردانید

def vati_isle (منبع: خواننده): # پروتکل به عنوان سرنخ نوع استفاده می شود
“” “داده ها از هر منبعی که متناسب با پروتکل خواننده باشد. “” “”
چاپ (“\ nveri در حال پردازش است …”)
داده = منبع.
چاپ (f “داده های پردازش شده: {data}”)
source.capat ()

file_okuyucu = پرونده (“config.ini”)
Socket_ocaker = سوکت (“192.168.1.100:8080”)
اشتباه = اشتباه
data_isle (file_okuyucu) # کار می کند ، زیرا پرونده از نظر ساختاری متناسب با خواننده است
data_isle (socket_okuyucu) # کار می کند زیرا سوکت از نظر ساختاری متناسب با خواننده است

چاپ (“\ Nanluish Reader Experiment:”)
سعی کنید:
data_isle (اشتباه)
به جز AttributeError به عنوان e:
چاپ (f “خطای گرفتار: {e}”)
جوانب مثبت: بدون نیاز به وراثت (انعطاف پذیرتر) ، استفاده از تایپ کردن اردک ، اما با کنترل نوع استاتیک ، تعریف پروتکل بدون تغییر کلاس های موجود ایمن تر است.
CVS: پایتون به 3.8+ نیاز دارد ، برای بهره مندی کامل به بازرسی های استاتیک (مانند MYPY) نیاز دارد و کنترل در محل کار می تواند مستقیماً از ABC (اما ممکن باشد) کمتر باشد.
4.4 پروتکل های غیررسمی (پروتکل های غیررسمی) / کنوانسیون
این تنها سست ترین رویکرد مبتنی بر صدور گواهینامه و کنوانسیون توسعه دهنده است. یک پروتکل یا رابط خاص فقط در مستندات تعریف می شود و از توسعه دهندگان انتظار می رود که این کنوانسیون را رعایت کنند. پایتون در بسیاری از مکان ها به خودی خود استفاده می شود (به عنوان مثال ، برای یک شی می تواند تکرار شود (قابل استفاده) تکرار همانطور که باید روش داشته باشد).

جوانب مثبت: بسیار انعطاف پذیر و حداقل نیاز به کد.
منفی: هیچ مکانیسم اجبار یا کنترل وجود ندارد ، کاملاً به رشته توسعه دهنده بستگی دارد ، خطاها فقط به زمان کار توجه می شوند.
فصل 5: کدام رویکرد را باید در پایتون انتخاب کند؟
انتخاب رویکرد درست بستگی به زمینه پروژه دارد:

برای کد ساده ، انعطاف پذیر یا پروژه های کوچک: معمولاً تایپ کردن اردک کافی است و پیتونیک ترین مسیر است. از توصیف غیر ضروری ABC یا پروتکل خودداری کنید.
اگر رفتار و ساختار اساسی مشترک مورد نیاز باشد: اگر گروهی از کلاس ها نیاز به به اشتراک گذاشتن یک اجرای مشترک و ارائه روش های خاص دارند ، کلاس های اساسی انتزاعی (ABC) انتخاب خوبی هستند. وراثت باید منطقی باشد (رابطه “IS-A”).
کتابخانه/چارچوب/طراحی API: ABC به طور کلی ترجیح داده می شود تا کاربران با یک رابط خاص مطابقت داشته باشند ، زیرا به قرارداد نیاز دارند.
کنترل نوع استاتیک برای طرح های انعطاف پذیر (Python 3.8+): اگر می خواهید کلاس های مختلفی با یک ساختار خاص بدون وراثت مطابقت داشته باشند ، و اگر می خواهید این موضوع را با ابزاری مانند MyPy تأیید کنید ، پروتکل ها یک جایگزین مدرن و قدرتمند هستند.
برای کنوانسیون بسیار ساده: فقط چند روش “جادویی” (لنبا تکرار پروتکل های غیررسمی ممکن است برای موقعیت هایی که نیاز دارند کافی باشد).
معمولاً ، این یک استراتژی منطقی است که با ساده ترین راه حل (تایپ اردک) شروع شود و به ABC یا پروتکل بپردازید زیرا نیازهای پروژه به ساختار یا امنیت بیشتری نیاز دارد.

فصل 6: مناطق استفاده و سناریوهای نمونه
ساختارهای مانند رابط در بسیاری از زمینه ها مفید هستند:

انتقال داده ها: انتزاع مکانیسم های مختلف ذخیره سازی (بانک اطلاعاتی ، پرونده ، ذخیره ابری) مکانیسم های مختلف ذخیره سازی. یک رابط کاربری مشترک (داده) ، بار (ID) می تواند تعریف شود.
ADD -ON (افزونه) سیستم ها: تعریف یک قرارداد (افزونه ABC یا پروتکل) که پلاگین برای گسترش برنامه اصلی است.
ذخیره سازی: استراتژی های مختلف حافظه پنهان (در -Memory ، Redis ، Memcached) را تحت رابط یک رابط Common GET (Key) ، مجموعه (کلید ، مقدار) ترکیب کنید.
سیستم های پیام رسانی (پیام رسانی): برای تعامل با صف پیام های مختلف (RabbitMQ ، Kafka ، SQS) ، یک رابط (پیام) ، AL () مشترک را ارائه دهید.
ادغام سیستم های پرداخت: انتزاع API ارائه دهندگان مختلف پرداخت (Strepe ، PayPal ، Braintre) تحت یک رابط پرداخت مشترک (نگهدارنده ، card_formation).
استراتژی های رتبه بندی و مقایسه: مرتب سازی شده () یا لیست. sort () برای مقایسه توابع کلیدی یا اشیاء آنبا معادله روشهای ویژه مانند استفاده از یک پروتکل خاص (مقایسه).
در آزمایشات ، از رابط ها برای ایجاد اشیاء تقلبی استفاده می شود که جایگزین اعتیاد خارجی (پایگاه داده ، سرویس شبکه) اعتیاد های خارجی (پایگاه داده ، سرویس شبکه) هنگام نوشتن تست های واحد می شوند.
فصل 7: نتیجه گیری: فکر رابط در پایتون
اگرچه هیچ کلمه کلیدی رابط سنتی در پایتون وجود ندارد ، اما مزایای اصلی رابط ها – شناسایی قرارداد ، اتصال شل ، پلی مورفیسم ، انعطاف پذیری – می تواند به طور مؤثر توسط مکانیسم های خود پایتون حاصل شود. ماهیت پویا زبان بر تایپ اردک تأکید دارد ، در حالی که پروتکل ها برای ساختار و نیازهای امنیتی بیشتر گزینه های محکمی را در کلاسهای اساسی اساسی (ABC) و پایتون مدرن ارائه می دهند.

نکته مهم این است که در مورد چگونگی تعامل مؤلفه های مختلف در کد شما و تعریف واضح این نقاط تعامل (رابط ها) فکر کنید. چه ضمنی (تایپ کردن اردک) یا باز (ABC ، ​​پروتکل ها) ، رابط های تعریف شده به خوبی کلیدهای مجموعه مدیریت هستند و باعث می شود کد مدولار تر شود و در طولانی مدت نرم افزار پایدارتر ، آزمایش شده و قابل توسعه را ایجاد کند.

کدام رویکرد شما انتخاب می کنید به الزامات ویژه پروژه شما ، ترجیحات تیم شما و توازن انعطاف پذیری/امنیتی مورد نظر شما بستگی دارد. دانستن این ابزارهای مختلفی که Python ارائه می دهد این قدرت را به شما می دهد که مناسب ترین راه حل برای هر موقعیت را انتخاب کنید.

عبدالکادیر گنگور – وب سایت شخصی
عبدالکادیر گنگور – وب سایت شخصی
عبدالکادیر گنگور – cv.
لوب
لوب
وابسته به لینکدین

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا